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 <patrick.147.norton@gmail.com>
  • Loading branch information
bors[bot] and PatrickNorton committed Aug 27, 2021
2 parents 125fbbd + 1597792 commit cf6c078
Showing 1 changed file with 87 additions and 0 deletions.
87 changes: 87 additions & 0 deletions src/biguint/iter.rs
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 cf6c078

Please sign in to comment.