Skip to content

Commit

Permalink
Merge branch 'master' into format-panic
Browse files Browse the repository at this point in the history
  • Loading branch information
phimuemue authored Sep 18, 2024
2 parents df96c73 + a31e14f commit b21f7aa
Show file tree
Hide file tree
Showing 14 changed files with 445 additions and 64 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- run: cargo test --all-features

miri:
runs-on: ubuntu-latest
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
components: miri
- uses: taiki-e/install-action@nextest
- run: |
cargo miri nextest run --all-features
cargo miri test --doc
check-format:
name: check format
runs-on: ubuntu-latest
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ either = { version = "1.0", default-features = false }

[dev-dependencies]
rand = "0.7"
criterion = "0.4.0"
criterion = { version = "0.4.0", features = ["html_reports"] }
paste = "1.0.0" # Used in test_std to instantiate generic tests
permutohedron = "0.2"
quickcheck = { version = "0.9", default_features = false }
Expand Down Expand Up @@ -75,3 +75,7 @@ harness = false
[[bench]]
name = "specializations"
harness = false

[[bench]]
name = "k_smallest"
harness = false
61 changes: 61 additions & 0 deletions benches/k_smallest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use criterion::{black_box, criterion_group, criterion_main, Bencher, BenchmarkId, Criterion};
use itertools::Itertools;
use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng};

fn strict(b: &mut Bencher, (k, vals): &(usize, &Vec<usize>)) {
b.iter(|| black_box(vals.iter()).k_smallest(*k))
}

fn relaxed(b: &mut Bencher, (k, vals): &(usize, &Vec<usize>)) {
b.iter(|| black_box(vals.iter()).k_smallest_relaxed(*k))
}

fn ascending(n: usize) -> Vec<usize> {
(0..n).collect()
}

fn random(n: usize) -> Vec<usize> {
let mut vals = (0..n).collect_vec();
vals.shuffle(&mut StdRng::seed_from_u64(42));
vals
}

fn descending(n: usize) -> Vec<usize> {
(0..n).rev().collect()
}

fn k_smallest(c: &mut Criterion, order: &str, vals: fn(usize) -> Vec<usize>) {
let mut g = c.benchmark_group(format!("k-smallest/{order}"));

for log_n in 20..23 {
let n = 1 << log_n;

let vals = vals(n);

for log_k in 7..10 {
let k = 1 << log_k;

let params = format!("{log_n}/{log_k}");
let input = (k, &vals);
g.bench_with_input(BenchmarkId::new("strict", &params), &input, strict);
g.bench_with_input(BenchmarkId::new("relaxed", &params), &input, relaxed);
}
}

g.finish()
}

fn k_smallest_asc(c: &mut Criterion) {
k_smallest(c, "asc", ascending);
}

fn k_smallest_rand(c: &mut Criterion) {
k_smallest(c, "rand", random);
}

fn k_smallest_desc(c: &mut Criterion) {
k_smallest(c, "desc", descending);
}

criterion_group!(benches, k_smallest_asc, k_smallest_rand, k_smallest_desc);
criterion_main!(benches);
45 changes: 13 additions & 32 deletions src/cons_tuples_impl.rs
Original file line number Diff line number Diff line change
@@ -1,58 +1,39 @@
use crate::adaptors::map::{MapSpecialCase, MapSpecialCaseFn};

macro_rules! impl_cons_iter(
($_A:ident, $_B:ident, ) => (); // stop

($A:ident, $($B:ident,)*) => (
impl_cons_iter!($($B,)*);
#[allow(non_snake_case)]
impl<X, Iter, $($B),*> Iterator for ConsTuples<Iter, (($($B,)*), X)>
where Iter: Iterator<Item = (($($B,)*), X)>,
{
type Item = ($($B,)* X, );
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(($($B,)*), x)| ($($B,)* x, ))
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
fn fold<Acc, Fold>(self, accum: Acc, mut f: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
self.iter.fold(accum, move |acc, (($($B,)*), x)| f(acc, ($($B,)* x, )))
impl<$($B),*, X> MapSpecialCaseFn<(($($B,)*), X)> for ConsTuplesFn {
type Out = ($($B,)* X, );
fn call(&mut self, (($($B,)*), X): (($($B,)*), X)) -> Self::Out {
($($B,)* X, )
}
}
);
);

impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,);

#[derive(Debug, Clone)]
pub struct ConsTuplesFn;

/// An iterator that maps an iterator of tuples like
/// `((A, B), C)` to an iterator of `(A, B, C)`.
///
/// Used by the `iproduct!()` macro.
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
#[derive(Debug)]
pub struct ConsTuples<I, J>
where
I: Iterator<Item = J>,
{
iter: I,
}

impl<I, J> Clone for ConsTuples<I, J>
where
I: Clone + Iterator<Item = J>,
{
clone_fields!(iter);
}
pub type ConsTuples<I> = MapSpecialCase<I, ConsTuplesFn>;

/// Create an iterator that maps for example iterators of
/// `((A, B), C)` to `(A, B, C)`.
pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I::IntoIter, J>
pub fn cons_tuples<I>(iterable: I) -> ConsTuples<I::IntoIter>
where
I: IntoIterator<Item = J>,
I: IntoIterator,
{
ConsTuples {
iter: iterable.into_iter(),
f: ConsTuplesFn,
}
}
2 changes: 1 addition & 1 deletion src/diff.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! "Diff"ing iterators for caching elements to sequential collections without requiring the new
//! elements' iterator to be `Clone`.
//!
//! - [`Diff`] (produced by the [`diff_with`] function)
//! [`Diff`] (produced by the [`diff_with`] function)
//! describes the difference between two non-`Clone` iterators `I` and `J` after breaking ASAP from
//! a lock-step comparison.

Expand Down
6 changes: 4 additions & 2 deletions src/free.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub use crate::zip_eq_impl::zip_eq;
/// ```
/// use itertools::intersperse;
///
/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]);
/// itertools::assert_equal(intersperse(0..3, 8), vec![0, 8, 1, 8, 2]);
/// ```
pub fn intersperse<I>(iterable: I, element: I::Item) -> Intersperse<I::IntoIter>
where
Expand All @@ -55,7 +55,7 @@ where
/// use itertools::intersperse_with;
///
/// let mut i = 10;
/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
/// itertools::assert_equal(intersperse_with(0..3, || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
/// assert_eq!(i, 8);
/// ```
pub fn intersperse_with<I, F>(iterable: I, element: F) -> IntersperseWith<I::IntoIter, F>
Expand All @@ -75,6 +75,7 @@ where
///
/// for (i, elt) in enumerate(&[1, 2, 3]) {
/// /* loop body */
/// # let _ = (i, elt);
/// }
/// ```
pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
Expand All @@ -93,6 +94,7 @@ where
///
/// for elt in rev(&[1, 2, 3]) {
/// /* loop body */
/// # let _ = elt;
/// }
/// ```
pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
Expand Down
40 changes: 40 additions & 0 deletions src/k_smallest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ where
storage
}

pub(crate) fn k_smallest_relaxed_general<I, F>(iter: I, k: usize, mut comparator: F) -> Vec<I::Item>
where
I: Iterator,
F: FnMut(&I::Item, &I::Item) -> Ordering,
{
if k == 0 {
iter.last();
return Vec::new();
}

let mut iter = iter.fuse();
let mut buf = iter.by_ref().take(2 * k).collect::<Vec<_>>();

if buf.len() < k {
buf.sort_unstable_by(&mut comparator);
return buf;
}

buf.select_nth_unstable_by(k - 1, &mut comparator);
buf.truncate(k);

iter.for_each(|val| {
if comparator(&val, &buf[k - 1]) != Ordering::Less {
return;
}

assert_ne!(buf.len(), buf.capacity());
buf.push(val);

if buf.len() == 2 * k {
buf.select_nth_unstable_by(k - 1, &mut comparator);
buf.truncate(k);
}
});

buf.sort_unstable_by(&mut comparator);
buf.truncate(k);
buf
}

#[inline]
pub(crate) fn key_to_cmp<T, K, F>(mut key: F) -> impl FnMut(&T, &T) -> Ordering
where
Expand Down
1 change: 1 addition & 0 deletions src/kmerge_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ impl<T, F: FnMut(&T, &T) -> bool> KMergePredicate<T> for F {
///
/// for elt in kmerge(vec![vec![0, 2, 4], vec![1, 3, 5], vec![6, 7]]) {
/// /* loop body */
/// # let _ = elt;
/// }
/// ```
pub fn kmerge<I>(iterable: I) -> KMerge<<I::Item as IntoIterator>::IntoIter>
Expand Down
Loading

0 comments on commit b21f7aa

Please sign in to comment.