From f718847290d0e438502a8412ba9706e1544689e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Sun, 28 Jun 2020 02:11:28 +0200 Subject: [PATCH 01/18] Add iter_u32_digits and iter_u64_digits to biguint --- benches/bigint.rs | 32 ++++++ src/biguint.rs | 286 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 295 insertions(+), 23 deletions(-) diff --git a/benches/bigint.rs b/benches/bigint.rs index 591e9a99..c2f7bd4d 100644 --- a/benches/bigint.rs +++ b/benches/bigint.rs @@ -393,3 +393,35 @@ fn modpow_even(b: &mut Bencher) { b.iter(|| base.modpow(&e, &m)); } + +#[bench] +fn to_u32_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.to_u32_digits()); +} + +#[bench] +fn iter_u32_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.iter_u32_digits().max()); +} + +#[bench] +fn to_u64_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.to_u64_digits()); +} + +#[bench] +fn iter_u64_digits(b: &mut Bencher) { + let mut rng = get_rng(); + let n = rng.gen_biguint(2048); + + b.iter(|| n.iter_u64_digits().max()); +} diff --git a/src/biguint.rs b/src/biguint.rs index 88365aa3..c9b7a512 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -8,7 +8,7 @@ use core::convert::TryFrom; use core::default::Default; use core::fmt; use core::hash; -use core::iter::{Product, Sum}; +use core::iter::{FusedIterator, Product, Sum}; use core::mem; use core::ops::{ Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign, @@ -2277,6 +2277,215 @@ pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { res } +#[cfg(u64_digit)] +pub struct IterU32Digits<'a> { + data: &'a [u64], + next_is_lo: bool, + last_hi_is_zero: bool, +} +#[cfg(u64_digit)] +impl<'a> IterU32Digits<'a> { + fn new(data: &'a [u64]) -> Self { + let last_hi_is_zero = data + .last() + .map(|&last| { + let last_hi = (last >> 32) as u32; + last_hi == 0 + }) + .unwrap_or(false); + IterU32Digits { + data, + next_is_lo: true, + last_hi_is_zero, + } + } +} +#[cfg(u64_digit)] +impl<'a> Iterator for IterU32Digits<'a> { + type Item = u32; + fn next(&mut self) -> Option { + match self.data.split_first() { + Some((&first, data)) => { + let next_is_lo = self.next_is_lo; + self.next_is_lo = !next_is_lo; + if next_is_lo { + Some(first as u32) + } else { + self.data = data; + if data.is_empty() && self.last_hi_is_zero { + self.last_hi_is_zero = false; + None + } else { + Some((first >> 32) as u32) + } + } + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + fn last(self) -> Option { + self.data.last().map(|&last| { + if self.last_hi_is_zero { + last as u32 + } else { + (last >> 32) as u32 + } + }) + } + + fn count(self) -> usize { + self.len() + } +} +#[cfg(u64_digit)] +impl<'a> ExactSizeIterator for IterU32Digits<'a> { + fn len(&self) -> usize { + self.data.len() * 2 - usize::from(self.last_hi_is_zero) + } +} + +#[cfg(not(u64_digit))] +pub struct IterU32Digits<'a> { + it: std::iter::Copied>, +} +#[cfg(not(u64_digit))] +impl<'a> IterU32Digits<'a> { + fn new(data: &'a [u32]) -> Self { + Self { + it: data.iter().copied(), + } + } +} +#[cfg(not(u64_digit))] +impl<'a> Iterator for IterU32Digits<'a> { + type Item = u32; + fn next(&mut self) -> Option { + self.it.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n) + } + + fn last(self) -> Option { + self.it.last() + } + + fn count(self) -> usize { + self.it.count() + } +} +#[cfg(not(u64_digit))] +impl<'a> ExactSizeIterator for IterU32Digits<'a> { + fn len(&self) -> usize { + self.it.len() + } +} + +impl<'a> FusedIterator for IterU32Digits<'a> {} + +#[cfg(not(u64_digit))] +pub struct IterU64Digits<'a> { + it: std::slice::Chunks<'a, u32>, +} +#[cfg(not(u64_digit))] +impl<'a> IterU64Digits<'a> { + fn new(data: &'a [u32]) -> Self { + IterU32Digits { it: data.chunks(2) } + } +} +#[cfg(not(u64_digit))] +impl<'a> Iterator for IterU64Digits<'a> { + type Item = u64; + fn next(&mut self) -> Option { + self.it.next(|chunk| { + let mut digit = chunk[0] as u64; + if let Some(&hi) = chunk.get(1) { + digit |= (hi as u64) << 32; + } + digit + }) + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + fn last(self) -> Option { + self.data.last().map(|&last| { + if self.last_hi_is_zero { + last as u32 + } else { + (last >> 32) as u32 + } + }) + } + + fn count(self) -> usize { + self.len() + } +} +#[cfg(not(u64_digit))] +impl<'a> ExactSizeIterator for IterU64Digits<'a> { + fn len(&self) -> usize { + self.data.len() * 2 - usize::from(self.last_hi_is_zero) + } +} + +#[cfg(u64_digit)] +pub struct IterU64Digits<'a> { + it: std::iter::Copied>, +} +#[cfg(u64_digit)] +impl<'a> IterU64Digits<'a> { + fn new(data: &'a [u64]) -> Self { + Self { + it: data.iter().copied(), + } + } +} +#[cfg(u64_digit)] +impl<'a> Iterator for IterU64Digits<'a> { + type Item = u64; + fn next(&mut self) -> Option { + self.it.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n) + } + + fn last(self) -> Option { + self.it.last() + } + + fn count(self) -> usize { + self.it.count() + } +} +#[cfg(u64_digit)] +impl<'a> ExactSizeIterator for IterU64Digits<'a> { + fn len(&self) -> usize { + self.it.len() + } +} +impl<'a> FusedIterator for IterU64Digits<'a> {} + /// Creates and initializes a `BigUint`. /// /// The digits are in little-endian base matching `BigDigit`. @@ -2531,6 +2740,24 @@ impl BigUint { } } + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).to_u64_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u64_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u64_digits(), vec![4294967296]); + /// assert_eq!(BigUint::from(112500000000u64).to_u64_digits(), vec![112500000000]); + /// ``` + #[inline] + pub fn to_u64_digits(&self) -> Vec { + self.iter_u64_digits().collect() + } + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit /// first. /// @@ -2546,30 +2773,43 @@ impl BigUint { /// ``` #[inline] pub fn to_u32_digits(&self) -> Vec { - let mut digits = Vec::new(); - - #[cfg(not(u64_digit))] - digits.clone_from(&self.data); + self.iter_u32_digits().collect() + } - #[cfg(u64_digit)] - { - if let Some((&last, data)) = self.data.split_last() { - let last_lo = last as u32; - let last_hi = (last >> 32) as u32; - let u32_len = data.len() * 2 + 1 + (last_hi != 0) as usize; - digits.reserve_exact(u32_len); - for &x in data { - digits.push(x as u32); - digits.push((x >> 32) as u32); - } - digits.push(last_lo); - if last_hi != 0 { - digits.push(last_hi); - } - } - } + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).iter_u32_digits().collect::>(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).iter_u32_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).iter_u32_digits().collect::>(), vec![0, 1]); + /// assert_eq!(BigUint::from(112500000000u64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn iter_u32_digits<'a>(&'a self) -> IterU32Digits<'a> { + IterU32Digits::new(self.data.as_slice()) + } - digits + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigUint; + /// + /// assert_eq!(BigUint::from(1125u32).iter_u64_digits().collect::>(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).iter_u64_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296]); + /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::>(), vec![112500000000]); + /// ``` + #[inline] + pub fn iter_u64_digits<'a>(&'a self) -> IterU64Digits<'a> { + IterU64Digits::new(self.data.as_slice()) } /// Returns the integer formatted as a string in the given radix. From 9f44a8fed4a1aeaa7c9ec1c04ef570a5fd01c5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Sun, 28 Jun 2020 02:24:32 +0200 Subject: [PATCH 02/18] add iter_u32_digits, iter_u64_digits, to_u64_digits to BigInt --- src/bigint.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/bigint.rs b/src/bigint.rs index 82d43db1..a7d2d458 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -31,7 +31,7 @@ use self::Sign::{Minus, NoSign, Plus}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; use crate::biguint; use crate::biguint::to_str_radix_reversed; -use crate::biguint::{BigUint, IntDigits}; +use crate::biguint::{BigUint, IntDigits, IterU32Digits, IterU64Digits}; use crate::ParseBigIntError; #[cfg(has_try_from)] use crate::TryFromBigIntError; @@ -2981,6 +2981,63 @@ impl BigInt { (self.sign, self.data.to_u32_digits()) } + /// Returns the sign and the `u32` digits representation of the `BigInt` ordered least + /// significant digit first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::{BigInt, Sign}; + /// + /// assert_eq!(BigInt::from(-1125).to_u64_digits(), (Sign::Minus, vec![1125])); + /// assert_eq!(BigInt::from(4294967295u32).to_u64_digits(), (Sign::Plus, vec![4294967295])); + /// assert_eq!(BigInt::from(4294967296u64).to_u64_digits(), (Sign::Plus, vec![4294967296])); + /// assert_eq!(BigInt::from(-112500000000i64).to_u64_digits(), (Sign::Minus, vec![112500000000])); + /// assert_eq!(BigInt::from(112500000000i64).to_u64_digits(), (Sign::Plus, vec![112500000000])); + /// ``` + #[inline] + pub fn to_u64_digits(&self) -> (Sign, Vec) { + (self.sign, self.data.to_u64_digits()) + } + + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigInt; + /// + /// assert_eq!(BigInt::from(-1125).iter_u32_digits().collect::>(), vec![1125]); + /// assert_eq!(BigInt::from(4294967295u32).iter_u32_digits().collect::>(), vec![4294967295]); + /// assert_eq!(BigInt::from(4294967296u64).iter_u32_digits().collect::>(), vec![0, 1]); + /// assert_eq!(BigInt::from(-112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// assert_eq!(BigInt::from(112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); + /// ``` + #[inline] + pub fn iter_u32_digits<'a>(&'a self) -> IterU32Digits<'a> { + self.data.iter_u32_digits() + } + + /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// first. + /// + /// # Examples + /// + /// ``` + /// use num_bigint::BigInt; + /// + /// assert_eq!(BigInt::from(-1125).iter_u64_digits().collect::>(), vec![1125u64]); + /// assert_eq!(BigInt::from(4294967295u32).iter_u64_digits().collect::>(), vec![4294967295u64]); + /// assert_eq!(BigInt::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296u64]); + /// assert_eq!(BigInt::from(-112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); + /// assert_eq!(BigInt::from(112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); + /// ``` + #[inline] + pub fn iter_u64_digits<'a>(&'a self) -> IterU64Digits<'a> { + self.data.iter_u64_digits() + } + /// Returns the two's-complement byte representation of the `BigInt` in big-endian byte order. /// /// # Examples From a00278ba94f38c8ba5d94d3fbd3e5242a2d27a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Sun, 28 Jun 2020 02:24:55 +0200 Subject: [PATCH 03/18] fix Copied is not available before 1.35.0 --- src/biguint.rs | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index c9b7a512..2ef6611f 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2352,21 +2352,19 @@ impl<'a> ExactSizeIterator for IterU32Digits<'a> { #[cfg(not(u64_digit))] pub struct IterU32Digits<'a> { - it: std::iter::Copied>, + it: std::slice::Iter<'a, u32>, } #[cfg(not(u64_digit))] impl<'a> IterU32Digits<'a> { fn new(data: &'a [u32]) -> Self { - Self { - it: data.iter().copied(), - } + Self { it: data.iter() } } } #[cfg(not(u64_digit))] impl<'a> Iterator for IterU32Digits<'a> { type Item = u32; fn next(&mut self) -> Option { - self.it.next() + self.it.next().map(|&t| t) } fn size_hint(&self) -> (usize, Option) { @@ -2374,11 +2372,11 @@ impl<'a> Iterator for IterU32Digits<'a> { } fn nth(&mut self, n: usize) -> Option { - self.it.nth(n) + self.it.nth(n).map(|&t| t) } fn last(self) -> Option { - self.it.last() + self.it.last().map(|&t| t) } fn count(self) -> usize { @@ -2445,21 +2443,19 @@ impl<'a> ExactSizeIterator for IterU64Digits<'a> { #[cfg(u64_digit)] pub struct IterU64Digits<'a> { - it: std::iter::Copied>, + it: std::slice::Iter<'a, u64>, } #[cfg(u64_digit)] impl<'a> IterU64Digits<'a> { fn new(data: &'a [u64]) -> Self { - Self { - it: data.iter().copied(), - } + Self { it: data.iter() } } } #[cfg(u64_digit)] impl<'a> Iterator for IterU64Digits<'a> { type Item = u64; fn next(&mut self) -> Option { - self.it.next() + self.it.next().map(|&t| t) } fn size_hint(&self) -> (usize, Option) { @@ -2467,11 +2463,11 @@ impl<'a> Iterator for IterU64Digits<'a> { } fn nth(&mut self, n: usize) -> Option { - self.it.nth(n) + self.it.nth(n).map(|&t| t) } fn last(self) -> Option { - self.it.last() + self.it.last().map(|&t| t) } fn count(self) -> usize { @@ -2748,14 +2744,14 @@ impl BigUint { /// ``` /// use num_bigint::BigUint; /// - /// assert_eq!(BigUint::from(1125u32).to_u64_digits(), vec![1125]); - /// assert_eq!(BigUint::from(4294967295u32).to_u64_digits(), vec![4294967295]); - /// assert_eq!(BigUint::from(4294967296u64).to_u64_digits(), vec![4294967296]); - /// assert_eq!(BigUint::from(112500000000u64).to_u64_digits(), vec![112500000000]); + /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); + /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); /// ``` #[inline] - pub fn to_u64_digits(&self) -> Vec { - self.iter_u64_digits().collect() + pub fn to_u32_digits(&self) -> Vec { + self.iter_u32_digits().collect() } /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit @@ -2766,14 +2762,14 @@ impl BigUint { /// ``` /// use num_bigint::BigUint; /// - /// assert_eq!(BigUint::from(1125u32).to_u32_digits(), vec![1125]); - /// assert_eq!(BigUint::from(4294967295u32).to_u32_digits(), vec![4294967295]); - /// assert_eq!(BigUint::from(4294967296u64).to_u32_digits(), vec![0, 1]); - /// assert_eq!(BigUint::from(112500000000u64).to_u32_digits(), vec![830850304, 26]); + /// assert_eq!(BigUint::from(1125u32).to_u64_digits(), vec![1125]); + /// assert_eq!(BigUint::from(4294967295u32).to_u64_digits(), vec![4294967295]); + /// assert_eq!(BigUint::from(4294967296u64).to_u64_digits(), vec![4294967296]); + /// assert_eq!(BigUint::from(112500000000u64).to_u64_digits(), vec![112500000000]); /// ``` #[inline] - pub fn to_u32_digits(&self) -> Vec { - self.iter_u32_digits().collect() + pub fn to_u64_digits(&self) -> Vec { + self.iter_u64_digits().collect() } /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit From 51a94c55284929cc559eff42b3db509c45bceb42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Sun, 28 Jun 2020 02:30:20 +0200 Subject: [PATCH 04/18] replace std::slice::x to core::slice::x --- src/biguint.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index 2ef6611f..64177e7d 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2352,7 +2352,7 @@ impl<'a> ExactSizeIterator for IterU32Digits<'a> { #[cfg(not(u64_digit))] pub struct IterU32Digits<'a> { - it: std::slice::Iter<'a, u32>, + it: core::slice::Iter<'a, u32>, } #[cfg(not(u64_digit))] impl<'a> IterU32Digits<'a> { @@ -2394,7 +2394,7 @@ impl<'a> FusedIterator for IterU32Digits<'a> {} #[cfg(not(u64_digit))] pub struct IterU64Digits<'a> { - it: std::slice::Chunks<'a, u32>, + it: core::slice::Chunks<'a, u32>, } #[cfg(not(u64_digit))] impl<'a> IterU64Digits<'a> { @@ -2443,7 +2443,7 @@ impl<'a> ExactSizeIterator for IterU64Digits<'a> { #[cfg(u64_digit)] pub struct IterU64Digits<'a> { - it: std::slice::Iter<'a, u64>, + it: core::slice::Iter<'a, u64>, } #[cfg(u64_digit)] impl<'a> IterU64Digits<'a> { From b0bed646a7b13c2947d9268c005858e063772320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Sun, 28 Jun 2020 02:39:11 +0200 Subject: [PATCH 05/18] fix 32bits build --- src/biguint.rs | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index 64177e7d..25dfbff0 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -176,6 +176,17 @@ impl FromStr for BigUint { } } +/// Convert a u32 chunk (len is either 1 or 2) to a single u64 digit +#[inline] +fn u32_chunk_to_u64(chunk: &[u32]) -> u64 { + // raw could have odd length + let mut digit = chunk[0] as u64; + if let Some(&hi) = chunk.get(1) { + digit |= (hi as u64) << 32; + } + digit +} + // Convert from a power of two radix (bits == ilog2(radix)) where bits evenly divides // BigDigit::BITS fn from_bitwise_digits_le(v: &[u8], bits: u8) -> BigUint { @@ -2399,20 +2410,15 @@ pub struct IterU64Digits<'a> { #[cfg(not(u64_digit))] impl<'a> IterU64Digits<'a> { fn new(data: &'a [u32]) -> Self { - IterU32Digits { it: data.chunks(2) } + IterU64Digits { it: data.chunks(2) } } } + #[cfg(not(u64_digit))] impl<'a> Iterator for IterU64Digits<'a> { type Item = u64; fn next(&mut self) -> Option { - self.it.next(|chunk| { - let mut digit = chunk[0] as u64; - if let Some(&hi) = chunk.get(1) { - digit |= (hi as u64) << 32; - } - digit - }) + self.it.next().map(u32_chunk_to_u64) } fn size_hint(&self) -> (usize, Option) { @@ -2420,14 +2426,8 @@ impl<'a> Iterator for IterU64Digits<'a> { (len, Some(len)) } - fn last(self) -> Option { - self.data.last().map(|&last| { - if self.last_hi_is_zero { - last as u32 - } else { - (last >> 32) as u32 - } - }) + fn last(self) -> Option { + self.it.last().map(u32_chunk_to_u64) } fn count(self) -> usize { @@ -2437,7 +2437,7 @@ impl<'a> Iterator for IterU64Digits<'a> { #[cfg(not(u64_digit))] impl<'a> ExactSizeIterator for IterU64Digits<'a> { fn len(&self) -> usize { - self.data.len() * 2 - usize::from(self.last_hi_is_zero) + self.it.len() } } @@ -2531,14 +2531,7 @@ impl BigUint { self.data.extend_from_slice(slice); #[cfg(u64_digit)] - self.data.extend(slice.chunks(2).map(|chunk| { - // raw could have odd length - let mut digit = BigDigit::from(chunk[0]); - if let Some(&hi) = chunk.get(1) { - digit |= BigDigit::from(hi) << 32; - } - digit - })); + self.data.extend(slice.chunks(2).map(u32_chunk_to_u64)); self.normalize(); } From d9e188b23cd0ec340b8145396caec5bb9bebd106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Wed, 19 Aug 2020 03:12:47 +0200 Subject: [PATCH 06/18] More idiomatic lifetime declaration & fix comments Co-authored-by: Josh Stone --- src/bigint.rs | 6 +++--- src/biguint.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index a7d2d458..00022a45 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -2981,7 +2981,7 @@ impl BigInt { (self.sign, self.data.to_u32_digits()) } - /// Returns the sign and the `u32` digits representation of the `BigInt` ordered least + /// Returns the sign and the `u64` digits representation of the `BigInt` ordered least /// significant digit first. /// /// # Examples @@ -3015,11 +3015,11 @@ impl BigInt { /// assert_eq!(BigInt::from(112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); /// ``` #[inline] - pub fn iter_u32_digits<'a>(&'a self) -> IterU32Digits<'a> { + pub fn iter_u32_digits(&self) -> IterU32Digits<'_> { self.data.iter_u32_digits() } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// Returns the `u64` digits representation of the `BigUint` ordered least significant digit /// first. /// /// # Examples diff --git a/src/biguint.rs b/src/biguint.rs index 25dfbff0..c05079fc 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2312,7 +2312,7 @@ impl<'a> IterU32Digits<'a> { } } #[cfg(u64_digit)] -impl<'a> Iterator for IterU32Digits<'a> { +impl Iterator for IterU32Digits<'_> { type Item = u32; fn next(&mut self) -> Option { match self.data.split_first() { @@ -2747,7 +2747,7 @@ impl BigUint { self.iter_u32_digits().collect() } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit + /// Returns the `u64` digits representation of the `BigUint` ordered least significant digit /// first. /// /// # Examples From d819767f01521059750efd199eba11dff19fdd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Wed, 19 Aug 2020 03:14:50 +0200 Subject: [PATCH 07/18] use iterator .cloned instead of map in IterU32Digits Co-authored-by: Josh Stone --- src/biguint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/biguint.rs b/src/biguint.rs index c05079fc..a1d796af 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2375,7 +2375,7 @@ impl<'a> IterU32Digits<'a> { impl<'a> Iterator for IterU32Digits<'a> { type Item = u32; fn next(&mut self) -> Option { - self.it.next().map(|&t| t) + self.it.next().cloned() } fn size_hint(&self) -> (usize, Option) { From 8168d805e6aba73d02fb5be12cc063ef8d47ccb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Wed, 19 Aug 2020 03:34:11 +0200 Subject: [PATCH 08/18] fix IterU32Digits len returns value is invalid --- src/biguint.rs | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/src/biguint.rs b/src/biguint.rs index a1d796af..e342aa07 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2357,7 +2357,7 @@ impl Iterator for IterU32Digits<'_> { #[cfg(u64_digit)] impl<'a> ExactSizeIterator for IterU32Digits<'a> { fn len(&self) -> usize { - self.data.len() * 2 - usize::from(self.last_hi_is_zero) + self.data.len() * 2 - usize::from(self.last_hi_is_zero) - usize::from(!self.next_is_lo) } } @@ -3372,3 +3372,45 @@ fn test_pow_biguint() { assert_eq!(BigUint::from(125u8), base.pow(exponent)); } + +#[test] +fn test_iter_u32_digits() { + let n = BigUint::from(5u8); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = BigUint::from(112500000000u64); + let mut it = n.iter_u32_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(830850304)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(26)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} + +#[test] +fn test_iter_u64_digits() { + let n = BigUint::from(5u8); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(5)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); + + let n = BigUint::from(18_446_744_073_709_551_616u128); + let mut it = n.iter_u64_digits(); + assert_eq!(it.len(), 2); + assert_eq!(it.next(), Some(0)); + assert_eq!(it.len(), 1); + assert_eq!(it.next(), Some(1)); + assert_eq!(it.len(), 0); + assert_eq!(it.next(), None); +} From 1f324ca11f9b17613792dd1c1dbff1d32429a662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Wed, 19 Aug 2020 03:34:54 +0200 Subject: [PATCH 09/18] fix iter_ux_digits comment --- src/bigint.rs | 8 ++++---- src/biguint.rs | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 00022a45..98152cf5 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -3000,8 +3000,8 @@ impl BigInt { (self.sign, self.data.to_u64_digits()) } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit - /// first. + /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least + /// significant digit first. /// /// # Examples /// @@ -3019,8 +3019,8 @@ impl BigInt { self.data.iter_u32_digits() } - /// Returns the `u64` digits representation of the `BigUint` ordered least significant digit - /// first. + /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least + /// significant digit first. /// /// # Examples /// diff --git a/src/biguint.rs b/src/biguint.rs index e342aa07..0c43dd27 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2765,8 +2765,8 @@ impl BigUint { self.iter_u64_digits().collect() } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit - /// first. + /// Returns an iterator of `u32` digits representation of the `BigUint` ordered least + /// significant digit first. /// /// # Examples /// @@ -2783,8 +2783,8 @@ impl BigUint { IterU32Digits::new(self.data.as_slice()) } - /// Returns the `u32` digits representation of the `BigUint` ordered least significant digit - /// first. + /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least + /// significant digit first. /// /// # Examples /// From 7c85952e4ca090ab7b42dab33907a84e6a67b146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouille=CC=81?= Date: Thu, 20 Aug 2020 02:41:38 +0200 Subject: [PATCH 10/18] more idiomatic iter_x_digits impl --- src/bigint.rs | 2 +- src/biguint.rs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 98152cf5..a0e84108 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -3034,7 +3034,7 @@ impl BigInt { /// assert_eq!(BigInt::from(112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); /// ``` #[inline] - pub fn iter_u64_digits<'a>(&'a self) -> IterU64Digits<'a> { + pub fn iter_u64_digits(&self) -> IterU64Digits<'_> { self.data.iter_u64_digits() } diff --git a/src/biguint.rs b/src/biguint.rs index 0c43dd27..a3ca2d5e 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2383,11 +2383,11 @@ impl<'a> Iterator for IterU32Digits<'a> { } fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).map(|&t| t) + self.it.nth(n).cloned() } fn last(self) -> Option { - self.it.last().map(|&t| t) + self.it.last().cloned() } fn count(self) -> usize { @@ -2455,7 +2455,7 @@ impl<'a> IterU64Digits<'a> { impl<'a> Iterator for IterU64Digits<'a> { type Item = u64; fn next(&mut self) -> Option { - self.it.next().map(|&t| t) + self.it.next().cloned() } fn size_hint(&self) -> (usize, Option) { @@ -2463,11 +2463,11 @@ impl<'a> Iterator for IterU64Digits<'a> { } fn nth(&mut self, n: usize) -> Option { - self.it.nth(n).map(|&t| t) + self.it.nth(n).cloned() } fn last(self) -> Option { - self.it.last().map(|&t| t) + self.it.last().cloned() } fn count(self) -> usize { @@ -2779,7 +2779,7 @@ impl BigUint { /// assert_eq!(BigUint::from(112500000000u64).iter_u32_digits().collect::>(), vec![830850304, 26]); /// ``` #[inline] - pub fn iter_u32_digits<'a>(&'a self) -> IterU32Digits<'a> { + pub fn iter_u32_digits(&self) -> IterU32Digits<'_> { IterU32Digits::new(self.data.as_slice()) } @@ -2797,7 +2797,7 @@ impl BigUint { /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::>(), vec![112500000000]); /// ``` #[inline] - pub fn iter_u64_digits<'a>(&'a self) -> IterU64Digits<'a> { + pub fn iter_u64_digits(&self) -> IterU64Digits<'_> { IterU64Digits::new(self.data.as_slice()) } From 3ee03f0b8f61753689c66c4a0b9578fcbe494600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouille=CC=81?= Date: Thu, 20 Aug 2020 02:42:20 +0200 Subject: [PATCH 11/18] fix iter_u32_digits comment --- src/bigint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigint.rs b/src/bigint.rs index a0e84108..8dd119fb 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -3000,7 +3000,7 @@ impl BigInt { (self.sign, self.data.to_u64_digits()) } - /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least + /// Returns an iterator of `u32` digits representation of the `BigUint` ordered least /// significant digit first. /// /// # Examples From 48310c11daa4a0990b676b61487bf6c0a43fe792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouille=CC=81?= Date: Thu, 20 Aug 2020 02:53:43 +0200 Subject: [PATCH 12/18] document IterUxDigits structs --- src/biguint.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index a3ca2d5e..c24af678 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2288,11 +2288,18 @@ pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { res } -#[cfg(u64_digit)] +/// An iterator of `u32` digits representation of the `BigUint` ordered least +/// significant digit first. pub struct IterU32Digits<'a> { + #[cfg(u64_digit)] data: &'a [u64], + #[cfg(u64_digit)] next_is_lo: bool, + #[cfg(u64_digit)] last_hi_is_zero: bool, + + #[cfg(not(u64_digit))] + it: core::slice::Iter<'a, u32>, } #[cfg(u64_digit)] impl<'a> IterU32Digits<'a> { @@ -2361,10 +2368,6 @@ impl<'a> ExactSizeIterator for IterU32Digits<'a> { } } -#[cfg(not(u64_digit))] -pub struct IterU32Digits<'a> { - it: core::slice::Iter<'a, u32>, -} #[cfg(not(u64_digit))] impl<'a> IterU32Digits<'a> { fn new(data: &'a [u32]) -> Self { @@ -2403,9 +2406,14 @@ impl<'a> ExactSizeIterator for IterU32Digits<'a> { impl<'a> FusedIterator for IterU32Digits<'a> {} -#[cfg(not(u64_digit))] +/// An iterator of `u64` digits representation of the `BigUint` ordered least +/// significant digit first. pub struct IterU64Digits<'a> { + #[cfg(not(u64_digit))] it: core::slice::Chunks<'a, u32>, + + #[cfg(u64_digit)] + it: core::slice::Iter<'a, u64>, } #[cfg(not(u64_digit))] impl<'a> IterU64Digits<'a> { @@ -2441,10 +2449,6 @@ impl<'a> ExactSizeIterator for IterU64Digits<'a> { } } -#[cfg(u64_digit)] -pub struct IterU64Digits<'a> { - it: core::slice::Iter<'a, u64>, -} #[cfg(u64_digit)] impl<'a> IterU64Digits<'a> { fn new(data: &'a [u64]) -> Self { From 2f9dc12d96a59d9190dc86914b1c815f8e9b01d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouille=CC=81?= Date: Thu, 20 Aug 2020 02:59:41 +0200 Subject: [PATCH 13/18] more idiomatic iter_x_digits impl --- src/biguint.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index c24af678..a8f22132 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2362,7 +2362,7 @@ impl Iterator for IterU32Digits<'_> { } } #[cfg(u64_digit)] -impl<'a> ExactSizeIterator for IterU32Digits<'a> { +impl ExactSizeIterator for IterU32Digits<'_> { fn len(&self) -> usize { self.data.len() * 2 - usize::from(self.last_hi_is_zero) - usize::from(!self.next_is_lo) } @@ -2375,7 +2375,7 @@ impl<'a> IterU32Digits<'a> { } } #[cfg(not(u64_digit))] -impl<'a> Iterator for IterU32Digits<'a> { +impl Iterator for IterU32Digits<'_> { type Item = u32; fn next(&mut self) -> Option { self.it.next().cloned() @@ -2398,13 +2398,13 @@ impl<'a> Iterator for IterU32Digits<'a> { } } #[cfg(not(u64_digit))] -impl<'a> ExactSizeIterator for IterU32Digits<'a> { +impl ExactSizeIterator for IterU32Digits<'_> { fn len(&self) -> usize { self.it.len() } } -impl<'a> FusedIterator for IterU32Digits<'a> {} +impl FusedIterator for IterU32Digits<'_> {} /// An iterator of `u64` digits representation of the `BigUint` ordered least /// significant digit first. @@ -2423,7 +2423,7 @@ impl<'a> IterU64Digits<'a> { } #[cfg(not(u64_digit))] -impl<'a> Iterator for IterU64Digits<'a> { +impl Iterator for IterU64Digits<'_> { type Item = u64; fn next(&mut self) -> Option { self.it.next().map(u32_chunk_to_u64) @@ -2443,7 +2443,7 @@ impl<'a> Iterator for IterU64Digits<'a> { } } #[cfg(not(u64_digit))] -impl<'a> ExactSizeIterator for IterU64Digits<'a> { +impl ExactSizeIterator for IterU64Digits<'_> { fn len(&self) -> usize { self.it.len() } @@ -2456,7 +2456,7 @@ impl<'a> IterU64Digits<'a> { } } #[cfg(u64_digit)] -impl<'a> Iterator for IterU64Digits<'a> { +impl Iterator for IterU64Digits<'_> { type Item = u64; fn next(&mut self) -> Option { self.it.next().cloned() @@ -2479,12 +2479,12 @@ impl<'a> Iterator for IterU64Digits<'a> { } } #[cfg(u64_digit)] -impl<'a> ExactSizeIterator for IterU64Digits<'a> { +impl ExactSizeIterator for IterU64Digits<'_> { fn len(&self) -> usize { self.it.len() } } -impl<'a> FusedIterator for IterU64Digits<'a> {} +impl FusedIterator for IterU64Digits<'_> {} /// Creates and initializes a `BigUint`. /// From aeb8e302dd5ad02ff7b677015f0b48703d967c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouille=CC=81?= Date: Fri, 21 Aug 2020 05:11:44 +0200 Subject: [PATCH 14/18] add inline mark to IterUXDigits --- src/biguint.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/biguint.rs b/src/biguint.rs index a8f22132..52c8ab9d 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2303,6 +2303,7 @@ pub struct IterU32Digits<'a> { } #[cfg(u64_digit)] impl<'a> IterU32Digits<'a> { + #[inline] fn new(data: &'a [u64]) -> Self { let last_hi_is_zero = data .last() @@ -2321,6 +2322,7 @@ impl<'a> IterU32Digits<'a> { #[cfg(u64_digit)] impl Iterator for IterU32Digits<'_> { type Item = u32; + #[inline] fn next(&mut self) -> Option { match self.data.split_first() { Some((&first, data)) => { @@ -2342,11 +2344,13 @@ impl Iterator for IterU32Digits<'_> { } } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } + #[inline] fn last(self) -> Option { self.data.last().map(|&last| { if self.last_hi_is_zero { @@ -2357,12 +2361,14 @@ impl Iterator for IterU32Digits<'_> { }) } + #[inline] fn count(self) -> usize { self.len() } } #[cfg(u64_digit)] impl ExactSizeIterator for IterU32Digits<'_> { + #[inline] fn len(&self) -> usize { self.data.len() * 2 - usize::from(self.last_hi_is_zero) - usize::from(!self.next_is_lo) } @@ -2370,6 +2376,7 @@ impl ExactSizeIterator for IterU32Digits<'_> { #[cfg(not(u64_digit))] impl<'a> IterU32Digits<'a> { + #[inline] fn new(data: &'a [u32]) -> Self { Self { it: data.iter() } } @@ -2377,28 +2384,34 @@ impl<'a> IterU32Digits<'a> { #[cfg(not(u64_digit))] impl Iterator for IterU32Digits<'_> { type Item = u32; + #[inline] fn next(&mut self) -> Option { self.it.next().cloned() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + #[inline] fn nth(&mut self, n: usize) -> Option { self.it.nth(n).cloned() } + #[inline] fn last(self) -> Option { self.it.last().cloned() } + #[inline] fn count(self) -> usize { self.it.count() } } #[cfg(not(u64_digit))] impl ExactSizeIterator for IterU32Digits<'_> { + #[inline] fn len(&self) -> usize { self.it.len() } @@ -2417,6 +2430,7 @@ pub struct IterU64Digits<'a> { } #[cfg(not(u64_digit))] impl<'a> IterU64Digits<'a> { + #[inline] fn new(data: &'a [u32]) -> Self { IterU64Digits { it: data.chunks(2) } } @@ -2425,25 +2439,30 @@ impl<'a> IterU64Digits<'a> { #[cfg(not(u64_digit))] impl Iterator for IterU64Digits<'_> { type Item = u64; + #[inline] fn next(&mut self) -> Option { self.it.next().map(u32_chunk_to_u64) } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } + #[inline] fn last(self) -> Option { self.it.last().map(u32_chunk_to_u64) } + #[inline] fn count(self) -> usize { self.len() } } #[cfg(not(u64_digit))] impl ExactSizeIterator for IterU64Digits<'_> { + #[inline] fn len(&self) -> usize { self.it.len() } @@ -2451,6 +2470,7 @@ impl ExactSizeIterator for IterU64Digits<'_> { #[cfg(u64_digit)] impl<'a> IterU64Digits<'a> { + #[inline] fn new(data: &'a [u64]) -> Self { Self { it: data.iter() } } @@ -2458,28 +2478,34 @@ impl<'a> IterU64Digits<'a> { #[cfg(u64_digit)] impl Iterator for IterU64Digits<'_> { type Item = u64; + #[inline] fn next(&mut self) -> Option { self.it.next().cloned() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.it.size_hint() } + #[inline] fn nth(&mut self, n: usize) -> Option { self.it.nth(n).cloned() } + #[inline] fn last(self) -> Option { self.it.last().cloned() } + #[inline] fn count(self) -> usize { self.it.count() } } #[cfg(u64_digit)] impl ExactSizeIterator for IterU64Digits<'_> { + #[inline] fn len(&self) -> usize { self.it.len() } From a25fec6eb3670ead5947652cd6c7d13c30938968 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Feb 2021 12:47:34 -0800 Subject: [PATCH 15/18] Rename iterators to U32Digits and U64Digits --- src/bigint.rs | 10 +++++----- src/biguint.rs | 52 +++++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/bigint.rs b/src/bigint.rs index 8dd119fb..9b9f1a8e 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -31,7 +31,7 @@ use self::Sign::{Minus, NoSign, Plus}; use crate::big_digit::{self, BigDigit, DoubleBigDigit}; use crate::biguint; use crate::biguint::to_str_radix_reversed; -use crate::biguint::{BigUint, IntDigits, IterU32Digits, IterU64Digits}; +use crate::biguint::{BigUint, IntDigits, U32Digits, U64Digits}; use crate::ParseBigIntError; #[cfg(has_try_from)] use crate::TryFromBigIntError; @@ -3000,7 +3000,7 @@ impl BigInt { (self.sign, self.data.to_u64_digits()) } - /// Returns an iterator of `u32` digits representation of the `BigUint` ordered least + /// Returns an iterator of `u32` digits representation of the `BigInt` ordered least /// significant digit first. /// /// # Examples @@ -3015,11 +3015,11 @@ impl BigInt { /// assert_eq!(BigInt::from(112500000000i64).iter_u32_digits().collect::>(), vec![830850304, 26]); /// ``` #[inline] - pub fn iter_u32_digits(&self) -> IterU32Digits<'_> { + pub fn iter_u32_digits(&self) -> U32Digits<'_> { self.data.iter_u32_digits() } - /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least + /// Returns an iterator of `u64` digits representation of the `BigInt` ordered least /// significant digit first. /// /// # Examples @@ -3034,7 +3034,7 @@ impl BigInt { /// assert_eq!(BigInt::from(112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); /// ``` #[inline] - pub fn iter_u64_digits(&self) -> IterU64Digits<'_> { + pub fn iter_u64_digits(&self) -> U64Digits<'_> { self.data.iter_u64_digits() } diff --git a/src/biguint.rs b/src/biguint.rs index 52c8ab9d..7585f0bc 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2288,9 +2288,9 @@ pub(crate) fn to_str_radix_reversed(u: &BigUint, radix: u32) -> Vec { res } -/// An iterator of `u32` digits representation of the `BigUint` ordered least -/// significant digit first. -pub struct IterU32Digits<'a> { +/// An iterator of `u32` digits representation of a `BigUint` or `BigInt`, +/// ordered least significant digit first. +pub struct U32Digits<'a> { #[cfg(u64_digit)] data: &'a [u64], #[cfg(u64_digit)] @@ -2302,7 +2302,7 @@ pub struct IterU32Digits<'a> { it: core::slice::Iter<'a, u32>, } #[cfg(u64_digit)] -impl<'a> IterU32Digits<'a> { +impl<'a> U32Digits<'a> { #[inline] fn new(data: &'a [u64]) -> Self { let last_hi_is_zero = data @@ -2312,7 +2312,7 @@ impl<'a> IterU32Digits<'a> { last_hi == 0 }) .unwrap_or(false); - IterU32Digits { + U32Digits { data, next_is_lo: true, last_hi_is_zero, @@ -2320,7 +2320,7 @@ impl<'a> IterU32Digits<'a> { } } #[cfg(u64_digit)] -impl Iterator for IterU32Digits<'_> { +impl Iterator for U32Digits<'_> { type Item = u32; #[inline] fn next(&mut self) -> Option { @@ -2367,7 +2367,7 @@ impl Iterator for IterU32Digits<'_> { } } #[cfg(u64_digit)] -impl ExactSizeIterator for IterU32Digits<'_> { +impl ExactSizeIterator for U32Digits<'_> { #[inline] fn len(&self) -> usize { self.data.len() * 2 - usize::from(self.last_hi_is_zero) - usize::from(!self.next_is_lo) @@ -2375,14 +2375,14 @@ impl ExactSizeIterator for IterU32Digits<'_> { } #[cfg(not(u64_digit))] -impl<'a> IterU32Digits<'a> { +impl<'a> U32Digits<'a> { #[inline] fn new(data: &'a [u32]) -> Self { Self { it: data.iter() } } } #[cfg(not(u64_digit))] -impl Iterator for IterU32Digits<'_> { +impl Iterator for U32Digits<'_> { type Item = u32; #[inline] fn next(&mut self) -> Option { @@ -2410,18 +2410,18 @@ impl Iterator for IterU32Digits<'_> { } } #[cfg(not(u64_digit))] -impl ExactSizeIterator for IterU32Digits<'_> { +impl ExactSizeIterator for U32Digits<'_> { #[inline] fn len(&self) -> usize { self.it.len() } } -impl FusedIterator for IterU32Digits<'_> {} +impl FusedIterator for U32Digits<'_> {} -/// An iterator of `u64` digits representation of the `BigUint` ordered least -/// significant digit first. -pub struct IterU64Digits<'a> { +/// An iterator of `u64` digits representation of a `BigUint` or `BigInt`, +/// ordered least significant digit first. +pub struct U64Digits<'a> { #[cfg(not(u64_digit))] it: core::slice::Chunks<'a, u32>, @@ -2429,15 +2429,15 @@ pub struct IterU64Digits<'a> { it: core::slice::Iter<'a, u64>, } #[cfg(not(u64_digit))] -impl<'a> IterU64Digits<'a> { +impl<'a> U64Digits<'a> { #[inline] fn new(data: &'a [u32]) -> Self { - IterU64Digits { it: data.chunks(2) } + U64Digits { it: data.chunks(2) } } } #[cfg(not(u64_digit))] -impl Iterator for IterU64Digits<'_> { +impl Iterator for U64Digits<'_> { type Item = u64; #[inline] fn next(&mut self) -> Option { @@ -2461,7 +2461,7 @@ impl Iterator for IterU64Digits<'_> { } } #[cfg(not(u64_digit))] -impl ExactSizeIterator for IterU64Digits<'_> { +impl ExactSizeIterator for U64Digits<'_> { #[inline] fn len(&self) -> usize { self.it.len() @@ -2469,14 +2469,14 @@ impl ExactSizeIterator for IterU64Digits<'_> { } #[cfg(u64_digit)] -impl<'a> IterU64Digits<'a> { +impl<'a> U64Digits<'a> { #[inline] fn new(data: &'a [u64]) -> Self { Self { it: data.iter() } } } #[cfg(u64_digit)] -impl Iterator for IterU64Digits<'_> { +impl Iterator for U64Digits<'_> { type Item = u64; #[inline] fn next(&mut self) -> Option { @@ -2504,13 +2504,13 @@ impl Iterator for IterU64Digits<'_> { } } #[cfg(u64_digit)] -impl ExactSizeIterator for IterU64Digits<'_> { +impl ExactSizeIterator for U64Digits<'_> { #[inline] fn len(&self) -> usize { self.it.len() } } -impl FusedIterator for IterU64Digits<'_> {} +impl FusedIterator for U64Digits<'_> {} /// Creates and initializes a `BigUint`. /// @@ -2809,8 +2809,8 @@ impl BigUint { /// assert_eq!(BigUint::from(112500000000u64).iter_u32_digits().collect::>(), vec![830850304, 26]); /// ``` #[inline] - pub fn iter_u32_digits(&self) -> IterU32Digits<'_> { - IterU32Digits::new(self.data.as_slice()) + pub fn iter_u32_digits(&self) -> U32Digits<'_> { + U32Digits::new(self.data.as_slice()) } /// Returns an iterator of `u64` digits representation of the `BigUint` ordered least @@ -2827,8 +2827,8 @@ impl BigUint { /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::>(), vec![112500000000]); /// ``` #[inline] - pub fn iter_u64_digits(&self) -> IterU64Digits<'_> { - IterU64Digits::new(self.data.as_slice()) + pub fn iter_u64_digits(&self) -> U64Digits<'_> { + U64Digits::new(self.data.as_slice()) } /// Returns the integer formatted as a string in the given radix. From 5f7471a3c8d455a91f78d2a745cdc6726978a01d Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Feb 2021 12:47:55 -0800 Subject: [PATCH 16/18] Re-export the iterators in the root --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 837a7d05..bfca016c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,6 +228,8 @@ impl fmt::Display for TryFromBigIntError { pub use crate::biguint::BigUint; pub use crate::biguint::ToBigUint; +pub use crate::biguint::U32Digits; +pub use crate::biguint::U64Digits; pub use crate::bigint::BigInt; pub use crate::bigint::Sign; From fea0bee4f59a03804212c19a693fc2a68c1c3c57 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Feb 2021 13:06:51 -0800 Subject: [PATCH 17/18] unify ExactSizeIterator for U64Digits --- src/biguint.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/biguint.rs b/src/biguint.rs index 7585f0bc..45e1fe65 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2301,6 +2301,7 @@ pub struct U32Digits<'a> { #[cfg(not(u64_digit))] it: core::slice::Iter<'a, u32>, } + #[cfg(u64_digit)] impl<'a> U32Digits<'a> { #[inline] @@ -2319,6 +2320,7 @@ impl<'a> U32Digits<'a> { } } } + #[cfg(u64_digit)] impl Iterator for U32Digits<'_> { type Item = u32; @@ -2366,6 +2368,7 @@ impl Iterator for U32Digits<'_> { self.len() } } + #[cfg(u64_digit)] impl ExactSizeIterator for U32Digits<'_> { #[inline] @@ -2381,6 +2384,7 @@ impl<'a> U32Digits<'a> { Self { it: data.iter() } } } + #[cfg(not(u64_digit))] impl Iterator for U32Digits<'_> { type Item = u32; @@ -2409,6 +2413,7 @@ impl Iterator for U32Digits<'_> { self.it.count() } } + #[cfg(not(u64_digit))] impl ExactSizeIterator for U32Digits<'_> { #[inline] @@ -2428,6 +2433,7 @@ pub struct U64Digits<'a> { #[cfg(u64_digit)] it: core::slice::Iter<'a, u64>, } + #[cfg(not(u64_digit))] impl<'a> U64Digits<'a> { #[inline] @@ -2460,13 +2466,6 @@ impl Iterator for U64Digits<'_> { self.len() } } -#[cfg(not(u64_digit))] -impl ExactSizeIterator for U64Digits<'_> { - #[inline] - fn len(&self) -> usize { - self.it.len() - } -} #[cfg(u64_digit)] impl<'a> U64Digits<'a> { @@ -2475,6 +2474,7 @@ impl<'a> U64Digits<'a> { Self { it: data.iter() } } } + #[cfg(u64_digit)] impl Iterator for U64Digits<'_> { type Item = u64; @@ -2503,13 +2503,14 @@ impl Iterator for U64Digits<'_> { self.it.count() } } -#[cfg(u64_digit)] + impl ExactSizeIterator for U64Digits<'_> { #[inline] fn len(&self) -> usize { self.it.len() } } + impl FusedIterator for U64Digits<'_> {} /// Creates and initializes a `BigUint`. From 0037a7f9dd045b4716570e049207d0b18b6b9f18 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 24 Feb 2021 13:47:22 -0800 Subject: [PATCH 18/18] Add multi-digit 64-bit examples --- src/bigint.rs | 2 ++ src/biguint.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/bigint.rs b/src/bigint.rs index 9b9f1a8e..aa3179d6 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -2994,6 +2994,7 @@ impl BigInt { /// assert_eq!(BigInt::from(4294967296u64).to_u64_digits(), (Sign::Plus, vec![4294967296])); /// assert_eq!(BigInt::from(-112500000000i64).to_u64_digits(), (Sign::Minus, vec![112500000000])); /// assert_eq!(BigInt::from(112500000000i64).to_u64_digits(), (Sign::Plus, vec![112500000000])); + /// assert_eq!(BigInt::from(1u128 << 64).to_u64_digits(), (Sign::Plus, vec![0, 1])); /// ``` #[inline] pub fn to_u64_digits(&self) -> (Sign, Vec) { @@ -3032,6 +3033,7 @@ impl BigInt { /// assert_eq!(BigInt::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296u64]); /// assert_eq!(BigInt::from(-112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); /// assert_eq!(BigInt::from(112500000000i64).iter_u64_digits().collect::>(), vec![112500000000u64]); + /// assert_eq!(BigInt::from(1u128 << 64).iter_u64_digits().collect::>(), vec![0, 1]); /// ``` #[inline] pub fn iter_u64_digits(&self) -> U64Digits<'_> { diff --git a/src/biguint.rs b/src/biguint.rs index 45e1fe65..64726faa 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -2790,6 +2790,7 @@ impl BigUint { /// assert_eq!(BigUint::from(4294967295u32).to_u64_digits(), vec![4294967295]); /// assert_eq!(BigUint::from(4294967296u64).to_u64_digits(), vec![4294967296]); /// assert_eq!(BigUint::from(112500000000u64).to_u64_digits(), vec![112500000000]); + /// assert_eq!(BigUint::from(1u128 << 64).to_u64_digits(), vec![0, 1]); /// ``` #[inline] pub fn to_u64_digits(&self) -> Vec { @@ -2826,6 +2827,7 @@ impl BigUint { /// assert_eq!(BigUint::from(4294967295u32).iter_u64_digits().collect::>(), vec![4294967295]); /// assert_eq!(BigUint::from(4294967296u64).iter_u64_digits().collect::>(), vec![4294967296]); /// assert_eq!(BigUint::from(112500000000u64).iter_u64_digits().collect::>(), vec![112500000000]); + /// assert_eq!(BigUint::from(1u128 << 64).iter_u64_digits().collect::>(), vec![0, 1]); /// ``` #[inline] pub fn iter_u64_digits(&self) -> U64Digits<'_> {