Skip to content

Commit

Permalink
switch to iterator implementation without unsafe for setu32 (also imp…
Browse files Browse the repository at this point in the history
…lement Clone for IntoIter)
  • Loading branch information
droundy committed Sep 14, 2024
1 parent 61f8375 commit a6bbd27
Show file tree
Hide file tree
Showing 2 changed files with 306 additions and 358 deletions.
361 changes: 3 additions & 358 deletions src/setu32.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![deny(missing_docs)]
//! This is a crate for the tiniest sets ever.
mod iter;

const fn num_bits<T>() -> u32 {
std::mem::size_of::<T>() as u32 * 8
}
Expand Down Expand Up @@ -372,294 +374,9 @@ enum InternalMut<'a> {
},
}

#[derive(Debug)]
enum Iter<'a> {
Empty,
Stack(Tiny),
Heap(HeapIter<'a>),
Big(BigIter<'a>),
Dense(DenseIter<'a>),
}

impl<'a> Iterator for Iter<'a> {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<u32> {
match self {
Iter::Empty => None,
Iter::Stack(t) => t.next(),
Iter::Dense(it) => it.next(),
Iter::Big(it) => it.next(),
Iter::Heap(it) => it.next(),
}
}
#[inline]
fn count(self) -> usize {
match self {
Iter::Empty => 0,
Iter::Stack(t) => t.count(),
Iter::Dense(it) => it.count(),
Iter::Big(it) => it.count(),
Iter::Heap(it) => it.count(),
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match self {
Iter::Empty => (0, Some(0)),
Iter::Stack(t) => t.size_hint(),
Iter::Dense(it) => it.size_hint(),
Iter::Big(it) => it.size_hint(),
Iter::Heap(it) => it.size_hint(),
}
}
#[inline]
fn min(self) -> Option<u32> {
match self {
Iter::Empty => None,
Iter::Stack(t) => t.min(),
Iter::Dense(it) => it.min(),
Iter::Big(it) => it.min(),
Iter::Heap(it) => it.min(),
}
}
#[inline]
fn max(self) -> Option<u32> {
match self {
Iter::Empty => None,
Iter::Stack(t) => t.max(),
Iter::Dense(it) => it.max(),
Iter::Big(it) => it.max(),
Iter::Heap(it) => it.max(),
}
}
#[inline]
fn last(self) -> Option<u32> {
match self {
Iter::Empty => None,
Iter::Stack(t) => t.last(),
Iter::Dense(it) => it.last(),
Iter::Big(it) => it.last(),
Iter::Heap(it) => it.last(),
}
}
}

#[derive(Debug)]
struct HeapIter<'a> {
sz_left: usize,
bits: u32,
whichbit: u32,
array: &'a [u32],
}

impl<'a> Iterator for HeapIter<'a> {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<u32> {
if self.bits > 0 {
while let Some(&x) = self.array.first() {
while self.whichbit < self.bits {
let oldbit = self.whichbit;
self.whichbit += 1;
if (x & (1 << oldbit)) != 0 {
self.sz_left -= 1;
return Some(unsplit_u32(x >> self.bits, oldbit, self.bits));
}
}
self.array = self.array.split_first().unwrap().1;
self.whichbit = 0;
}
} else {
if let Some((&first, rest)) = self.array.split_first() {
self.array = rest;
self.sz_left -= 1;
return Some(first);
}
}
None
}
#[inline]
fn last(self) -> Option<u32> {
self.array
.into_iter()
.rev()
.cloned()
.filter(|&x| x != 0)
.map(|x| x >> self.bits + (x & mask(self.bits as usize)).leading_zeros() - 31)
.next()
}
#[inline]
fn count(self) -> usize {
self.sz_left
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.sz_left, Some(self.sz_left))
}
#[inline]
fn min(mut self) -> Option<u32> {
if self.sz_left == 0 {
None
} else if self.whichbit == 0 {
let x = self
.array
.into_iter()
.cloned()
.filter(|x| *x != 0)
.min()
.unwrap();
Some((x >> self.bits) * self.bits + x.trailing_zeros() as u32)
} else {
let mut min = self.next().unwrap();
while let Some(x) = self.next() {
if x < min {
min = x;
}
}
Some(min)
}
}
#[inline]
fn max(mut self) -> Option<u32> {
if self.sz_left == 0 {
None
} else if self.whichbit == 0 {
let x = self
.array
.into_iter()
.cloned()
.filter(|x| *x != 0)
.max()
.unwrap();
let reference = (x >> self.bits) * self.bits;
let m = mask(self.bits as usize);
let extra = 31 - (x & m).leading_zeros();
Some(reference + extra)
} else {
let mut max = self.next().unwrap();
while let Some(x) = self.next() {
if x > max {
max = x;
}
}
Some(max)
}
}
}

#[derive(Debug)]
struct BigIter<'a> {
sz_left: usize,
bits: u32,
a: &'a [u32],
}

impl<'a> Iterator for BigIter<'a> {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<u32> {
while let Some((&x, rest)) = self.a.split_first() {
self.a = rest;
if x != 0 {
self.sz_left -= 1;
return Some(if x == self.bits { 0 } else { x });
}
}
None
}
#[inline]
fn last(self) -> Option<u32> {
self.a
.into_iter()
.rev()
.cloned()
.filter(|&x| x != 0)
.map(|x| if x == self.bits { 0 } else { x })
.next()
}
#[inline]
fn count(self) -> usize {
self.sz_left
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.sz_left, Some(self.sz_left))
}
#[inline]
fn min(self) -> Option<u32> {
if self.sz_left == 0 {
None
} else {
self.a
.into_iter()
.cloned()
.filter(|x| *x != 0)
.map(|x| if x == self.bits { 0 } else { x })
.min()
}
}
}

#[derive(Debug)]
struct DenseIter<'a> {
sz_left: usize,
whichword: usize,
whichbit: u32,
a: &'a [u32],
}

impl<'a> Iterator for DenseIter<'a> {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<u32> {
loop {
if let Some(word) = self.a.get(self.whichword) {
while self.whichbit < 32 {
let bit = self.whichbit;
self.whichbit = 1 + bit;
if word & (1 << bit) != 0 {
self.sz_left -= 1;
return Some(((self.whichword as u32) << 5) + bit as u32);
}
}
self.whichbit = 0;
self.whichword += 1;
} else {
return None;
}
}
}
#[inline]
fn last(self) -> Option<u32> {
if self.sz_left == 0 {
return None;
}
let zero_words = self.a.iter().rev().cloned().take_while(|&x| x == 0).count() as u32;
let zero_bits = self.a[self.a.len() - 1 - zero_words as usize].leading_zeros() as u32;
Some(self.a.len() as u32 * 32 - zero_bits - 1 - zero_words * 32)
}
#[inline]
fn max(self) -> Option<u32> {
self.last()
}
#[inline]
fn count(self) -> usize {
self.sz_left
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.sz_left, Some(self.sz_left))
}
#[inline]
fn min(mut self) -> Option<u32> {
self.next()
}
}

impl crate::copyset::CopySet for SetU32 {
type Item = u32;
type Iter = IntoIter;
type Iter = iter::IntoIter;
fn ins(&mut self, e: u32) -> bool {
self.insert(e)
}
Expand All @@ -680,13 +397,6 @@ impl crate::copyset::CopySet for SetU32 {
}
}

/// An iterator over a set of `u32`.
#[derive(Debug)]
pub struct IntoIter {
iter: Iter<'static>,
_set: SetU32,
}

impl Extend<u32> for SetU32 {
fn extend<T: IntoIterator<Item = u32>>(&mut self, iter: T) {
for i in iter.into_iter() {
Expand Down Expand Up @@ -909,43 +619,6 @@ mod serde {
}
}

impl IntoIterator for SetU32 {
type Item = u32;
type IntoIter = IntoIter;

fn into_iter(self) -> IntoIter {
let iter = unsafe { std::mem::transmute(self.private_iter()) };
IntoIter { iter, _set: self }
}
}
impl Iterator for IntoIter {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn last(self) -> Option<Self::Item> {
self.iter.last()
}
#[inline]
fn min(self) -> Option<Self::Item> {
self.iter.min()
}
#[inline]
fn max(self) -> Option<Self::Item> {
self.iter.max()
}
#[inline]
fn count(self) -> usize {
self.iter.count()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl Clone for SetU32 {
fn clone(&self) -> Self {
if self.0 as usize & 7 == 0 && self.0 != std::ptr::null_mut() {
Expand Down Expand Up @@ -1495,34 +1168,6 @@ impl SetU32 {
}
}

/// Iterate over
#[inline]
pub fn iter<'a>(&'a self) -> impl Iterator<Item = u32> + 'a + std::fmt::Debug {
self.private_iter()
}
fn private_iter<'a>(&'a self) -> Iter<'a> {
match self.internal() {
Internal::Empty => Iter::Empty,
Internal::Stack(t) => Iter::Stack(t),
Internal::Heap { s, a } => Iter::Heap(HeapIter {
sz_left: s.sz as usize,
bits: s.bits,
whichbit: 0,
array: a,
}),
Internal::Big { s, a } => Iter::Big(BigIter {
sz_left: s.sz as usize,
bits: s.bits,
a,
}),
Internal::Dense { a, sz } => Iter::Dense(DenseIter {
sz_left: sz as usize,
whichword: 0,
whichbit: 0,
a,
}),
}
}
/// Clears the set, returning all elements in an iterator.
#[inline]
pub fn drain<'a>(&'a mut self) -> impl Iterator<Item = u32> + 'a {
Expand Down
Loading

0 comments on commit a6bbd27

Please sign in to comment.