Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 9 additions & 45 deletions src/combinations.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use core::array;
use core::borrow::BorrowMut;
use std::fmt;
use std::iter::FusedIterator;

use super::lazy_buffer::LazyBuffer;
use super::lazy_buffer::{LazyBuffer, ArrayOrVecHelper};
use alloc::vec::Vec;

use crate::adaptors::checked_binomial;
use crate::lazy_buffer::MaybeConstUsize as _;

/// Iterator for `Vec` valued combinations returned by [`.combinations()`](crate::Itertools::combinations)
pub type Combinations<I> = CombinationsGeneric<I, Vec<usize>>;
Expand Down Expand Up @@ -39,42 +39,6 @@ pub struct CombinationsGeneric<I: Iterator, Idx> {
first: bool,
}

/// A type holding indices of elements in a pool or buffer of items from an inner iterator
/// and used to pick out different combinations in a generic way.
pub trait PoolIndex<T>: BorrowMut<[usize]> {
type Item;

fn extract_item<I: Iterator<Item = T>>(&self, pool: &LazyBuffer<I>) -> Self::Item
where
T: Clone;

fn len(&self) -> usize {
self.borrow().len()
}
}

impl<T> PoolIndex<T> for Vec<usize> {
type Item = Vec<T>;

fn extract_item<I: Iterator<Item = T>>(&self, pool: &LazyBuffer<I>) -> Vec<T>
where
T: Clone,
{
pool.get_at(self)
}
}

impl<T, const K: usize> PoolIndex<T> for [usize; K] {
type Item = [T; K];

fn extract_item<I: Iterator<Item = T>>(&self, pool: &LazyBuffer<I>) -> [T; K]
where
T: Clone,
{
pool.get_array(*self)
}
}

impl<I, Idx> Clone for CombinationsGeneric<I, Idx>
where
I: Iterator + Clone,
Expand All @@ -93,7 +57,7 @@ where
debug_fmt_fields!(Combinations, indices, pool, first);
}

impl<I: Iterator, Idx: PoolIndex<I::Item>> CombinationsGeneric<I, Idx> {
impl<I: Iterator, Idx: ArrayOrVecHelper> CombinationsGeneric<I, Idx> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is Idx still a good name if the trait is ArrayOrVecHelper?

/// Constructor with arguments the inner iterator and the initial state for the indices.
fn new(iter: I, indices: Idx) -> Self {
Self {
Expand All @@ -105,7 +69,7 @@ impl<I: Iterator, Idx: PoolIndex<I::Item>> CombinationsGeneric<I, Idx> {

/// Returns the length of a combination produced by this iterator.
#[inline]
pub fn k(&self) -> usize {
pub fn k(&self) -> Idx::Length {
self.indices.len()
}

Expand Down Expand Up @@ -136,8 +100,8 @@ impl<I: Iterator, Idx: PoolIndex<I::Item>> CombinationsGeneric<I, Idx> {
/// Initialises the iterator by filling a buffer with elements from the
/// iterator. Returns true if there are no combinations, false otherwise.
fn init(&mut self) -> bool {
self.pool.prefill(self.k());
let done = self.k() > self.n();
self.pool.prefill(self.k().value());
let done = self.k().value() > self.n();
if !done {
self.first = false;
}
Expand Down Expand Up @@ -210,9 +174,9 @@ impl<I, Idx> Iterator for CombinationsGeneric<I, Idx>
where
I: Iterator,
I::Item: Clone,
Idx: PoolIndex<I::Item>,
Idx: ArrayOrVecHelper,
{
type Item = Idx::Item;
type Item = Idx::Item<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
let done = if self.first {
self.init()
Expand Down Expand Up @@ -248,7 +212,7 @@ impl<I, Idx> FusedIterator for CombinationsGeneric<I, Idx>
where
I: Iterator,
I::Item: Clone,
Idx: PoolIndex<I::Item>,
Idx: ArrayOrVecHelper,
{
}

Expand Down
94 changes: 94 additions & 0 deletions src/lazy_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloc::vec::Vec;
use core::borrow::BorrowMut;
use std::iter::Fuse;
use std::ops::Index;

Expand Down Expand Up @@ -77,3 +78,96 @@ where
self.buffer.index(index)
}
}

pub trait MaybeConstUsize: Clone + Copy + std::fmt::Debug {
/*TODO const*/
fn value(self) -> usize;
}

#[derive(Clone, Copy, Debug)]
pub struct ConstUsize<const N: usize>;
impl<const N: usize> MaybeConstUsize for ConstUsize<N> {
fn value(self) -> usize {
N
}
}

impl MaybeConstUsize for usize {
fn value(self) -> usize {
self
}
}

/// A type holding indices of elements in a pool or buffer of items from an inner iterator
/// and used to pick out different combinations in a generic way.
pub trait ArrayOrVecHelper: BorrowMut<[usize]> {
type Item<T>;
type Length: MaybeConstUsize;

fn extract_item<I: Iterator>(&self, pool: &LazyBuffer<I>) -> Self::Item<I::Item>
where
I::Item: Clone;

// TODO if only ever used to index into LazyBuffer, specialize to
// extract_from_fn(Self::Length, Fn(usize) -> usize, &LazyBuffer) -> Item<T>?
fn item_from_fn<T, F: Fn(usize) -> T>(len: Self::Length, f: F) -> Self::Item<T>;

fn len(&self) -> Self::Length;

fn from_fn<F: Fn(usize) -> usize>(k: Self::Length, f: F) -> Self;

fn start(len: Self::Length) -> Self
where
Self: Sized,
{
Self::from_fn(len, |i| i)
}
}

impl ArrayOrVecHelper for Vec<usize> {
type Item<T> = Vec<T>;
type Length = usize;

fn extract_item<I: Iterator>(&self, pool: &LazyBuffer<I>) -> Self::Item<I::Item>
where
I::Item: Clone,
{
pool.get_at(self)
}

fn item_from_fn<T, F: Fn(usize) -> T>(len: Self::Length, f: F) -> Self::Item<T> {
(0..len).map(f).collect()
}

fn len(&self) -> Self::Length {
self.len()
}

fn from_fn<F: Fn(usize) -> usize>(k: Self::Length, f: F) -> Self {
(0..k).map(f).collect()
}
}

impl<const K: usize> ArrayOrVecHelper for [usize; K] {
type Item<T> = [T; K];
type Length = ConstUsize<K>;

fn extract_item<I: Iterator>(&self, pool: &LazyBuffer<I>) -> Self::Item<I::Item>
where
I::Item: Clone,
{
pool.get_array(*self)
}

fn item_from_fn<T, F: Fn(usize) -> T>(_len: Self::Length, f: F) -> Self::Item<T> {
std::array::from_fn(f)
}

fn len(&self) -> Self::Length {
ConstUsize::<K>
}

fn from_fn<F: Fn(usize) -> usize>(_len: Self::Length, f: F) -> Self {
std::array::from_fn(f)
}
}
Loading