Skip to content

Commit

Permalink
Merge #208
Browse files Browse the repository at this point in the history
208: Add `DoubleEndedIterator` to `U32Digits` and `U64Digits` r=cuviper a=PatrickNorton

Since `U32Digits` and `U64Digits` do not implement `DoubleEndedIterator`, there is currently no easy way to iterate over the digits in a big-ended fashion.

Co-authored-by: Patrick Norton <[email protected]>
Co-authored-by: Josh Stone <[email protected]>
  • Loading branch information
3 people authored Aug 27, 2021
2 parents 125fbbd + 25e9628 commit 3753602
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
3 changes: 3 additions & 0 deletions ci/test_full.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ if [ -n "${NO_STD_FEATURES[*]}" ]; then
echo " no_std supported features: ${NO_STD_FEATURES[*]}"
fi

# arbitrary 1.0.1 added const-generic arrays, which requires Rust 1.51
check_version 1.51.0 || cargo update -p arbitrary --precise 1.0.0

set -x

# test the default with std
Expand Down
87 changes: 87 additions & 0 deletions src/biguint/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,30 @@ impl Iterator for U32Digits<'_> {
}
}

#[cfg(u64_digit)]
impl DoubleEndedIterator for U32Digits<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
match self.data.split_last() {
Some((&last, data)) => {
let last_is_lo = self.last_hi_is_zero;
self.last_hi_is_zero = !last_is_lo;
if last_is_lo {
self.data = data;
if data.is_empty() && !self.next_is_lo {
self.next_is_lo = true;
None
} else {
Some(last as u32)
}
} else {
Some((last >> 32) as u32)
}
}
None => None,
}
}
}

#[cfg(u64_digit)]
impl ExactSizeIterator for U32Digits<'_> {
#[inline]
Expand Down Expand Up @@ -129,6 +153,13 @@ impl Iterator for U32Digits<'_> {
}
}

#[cfg(not(u64_digit))]
impl DoubleEndedIterator for U32Digits<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.it.next_back().copied()
}
}

#[cfg(not(u64_digit))]
impl ExactSizeIterator for U32Digits<'_> {
#[inline]
Expand Down Expand Up @@ -182,6 +213,13 @@ impl Iterator for U64Digits<'_> {
}
}

#[cfg(not(u64_digit))]
impl DoubleEndedIterator for U64Digits<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.it.next_back().map(u32_chunk_to_u64)
}
}

#[cfg(u64_digit)]
impl<'a> U64Digits<'a> {
#[inline]
Expand Down Expand Up @@ -219,6 +257,13 @@ impl Iterator for U64Digits<'_> {
}
}

#[cfg(u64_digit)]
impl DoubleEndedIterator for U64Digits<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.it.next_back().cloned()
}
}

impl ExactSizeIterator for U64Digits<'_> {
#[inline]
fn len(&self) -> usize {
Expand Down Expand Up @@ -269,3 +314,45 @@ fn test_iter_u64_digits() {
assert_eq!(it.len(), 0);
assert_eq!(it.next(), None);
}

#[test]
fn test_iter_u32_digits_be() {
let n = super::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 = super::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_be() {
let n = super::BigUint::from(5u8);
let mut it = n.iter_u64_digits();
assert_eq!(it.len(), 1);
assert_eq!(it.next_back(), Some(5));
assert_eq!(it.len(), 0);
assert_eq!(it.next(), None);
assert_eq!(it.len(), 0);
assert_eq!(it.next(), None);

let n = super::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_back(), Some(1));
assert_eq!(it.len(), 1);
assert_eq!(it.next_back(), Some(0));
assert_eq!(it.len(), 0);
assert_eq!(it.next(), None);
}

0 comments on commit 3753602

Please sign in to comment.