Skip to content

Commit

Permalink
Add Combinations::from_slice() constructor, and use within Powerset
Browse files Browse the repository at this point in the history
Adds a faster constructor for Combinations, usable when the source is a
known quantity and can be passed as a slice. Improves Powerset
performance for some small sizes of Powerset.
  • Loading branch information
willcrozi committed Mar 1, 2019
1 parent 925e780 commit 9faaec7
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 20 deletions.
41 changes: 28 additions & 13 deletions src/combinations.rs
@@ -1,6 +1,7 @@

use std::ops::Index;
use std::fmt;
use std::iter::{self, Empty};

/// An iterator to iterate through all the `n`-length combinations in an iterator.
///
Expand All @@ -20,31 +21,37 @@ impl<I> fmt::Debug for Combinations<I>
debug_fmt_fields!(Combinations, n, indices, pool, first);
}

/// Create a new `Combinations` from a clonable iterator.
/// Create a new `Combinations` from a cloneable iterator.
pub fn combinations<I>(iter: I, n: usize) -> Combinations<I>
where I: Iterator
{
let mut indices: Vec<usize> = Vec::with_capacity(n);
for i in 0..n {
indices.push(i);
}
let mut pool: LazyBuffer<I> = LazyBuffer::new(iter);

for _ in 0..n {
if !pool.get_next() {
break;
}
}
Combinations::new(n, pool)
}

Combinations {
n: n,
indices: indices,
pool: pool,
first: true,
impl<I> Combinations<I>
where I: Iterator
{
fn new(n: usize, pool: LazyBuffer<I>) -> Combinations<I> {
Combinations {
n: n,
indices: (0..n).collect(),
pool: pool,
first: true,
}
}

/// Fast construction from a slice.
pub(crate) fn from_slice<T: Clone>(src: &[T], n: usize) -> Combinations<Empty<T>> {
let pool = LazyBuffer::<Empty<T>>::from_slice(src);
Combinations::new(n, pool)
}
}

impl<I: Iterator> Combinations<I> {
#[inline]
/// Returns the length of a combination produced by this iterator.
pub fn n(&self) -> usize { self.n }
Expand Down Expand Up @@ -132,6 +139,14 @@ impl<I> LazyBuffer<I>
}
}

fn from_slice<T: Clone>(src: &[T]) -> LazyBuffer<Empty<T>> {
LazyBuffer {
it: iter::empty::<T>(),
done: true,
buffer: src.to_owned(),
}
}

pub fn len(&self) -> usize {
self.buffer.len()
}
Expand Down
12 changes: 5 additions & 7 deletions src/powerset.rs
@@ -1,7 +1,7 @@
use std::vec::IntoIter;
use std::fmt;
use std::usize;
use super::combinations::{self, Combinations};
use std::iter::{self, Empty};
use super::combinations::Combinations;
use super::size_hint;

/// An iterator over the powerset of all elements from its source iterator.
Expand All @@ -17,7 +17,7 @@ pub struct Powerset<I: Iterator> {
pos: usize,
}

type SetCombinations<I> = Combinations<IntoIter<<I as Iterator>::Item>>;
type SetCombinations<I> = Combinations<iter::Empty<<I as Iterator>::Item>>;

impl<I> fmt::Debug for Powerset<I>
where I: Iterator + fmt::Debug,
Expand All @@ -28,8 +28,7 @@ impl<I> fmt::Debug for Powerset<I>

/// Create a new `Powerset` from a cloneable iterator.
pub fn powerset<I>(src: I) -> Powerset<I>
where I: Iterator,
I::Item: Clone
where I: Iterator
{
let (src_low, _) = src.size_hint();

Expand Down Expand Up @@ -57,8 +56,7 @@ impl<I> Powerset<I>
None => 2
};

let iter = self.buf.clone().into_iter();
let mut combs = combinations::combinations(iter, new_len);
let mut combs = Combinations::<Empty<I::Item>>::from_slice(&self.buf[..], new_len);
let result = combs.next();
self.combs = Some(combs);

Expand Down

0 comments on commit 9faaec7

Please sign in to comment.