diff --git a/Cargo.toml b/Cargo.toml index 8343c80..cffa41f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "median-accumulator" version = "0.4.0" -edition = "2021" +edition = "2024" authors = ["tuxmain "] license = "AGPL-3.0-only" repository = "https://git.txmn.tk/tuxmain/median-accumulator" @@ -11,7 +11,7 @@ categories = ["algorithms", "data-structures", "no-std"] keywords = ["median"] [dependencies] -cc-traits = { version = "2.0.0", default_features = false } +cc-traits = { version = "2.0.0", default-features = false } smallvec = { version = "^1.6", optional = true } [features] @@ -21,9 +21,9 @@ smallvec = ["dep:smallvec", "cc-traits/smallvec"] default = ["std"] [dev-dependencies] -criterion = { version = "0.5.1", features = ["html_reports"] } +criterion = { version = "0.8.2", features = ["html_reports"] } medianheap = "0.4.1" -rand = "0.8.5" +rand = "0.10" smallvec = "^1.6" [[bench]] diff --git a/README.md b/README.md index 5bb954e..8e7161b 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ For other collections than `Vec` or `SmallVec`, you must implement [cc-traits](h ## License -CopyLeft 2022-2024 Pascal Engélibert [(why copyleft?)](https://txmn.tk/blog/why-copyleft/) +CopyLeft 2022-2026 Pascal Engélibert [(why copyleft?)](https://txmn.tk/blog/why-copyleft/) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License. diff --git a/benches/comparison.rs b/benches/comparison.rs index cee27cc..0fcf3ee 100644 --- a/benches/comparison.rs +++ b/benches/comparison.rs @@ -1,14 +1,14 @@ -use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion}; -use rand::Rng; +use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; +use rand::RngExt; static ITERS: u32 = 10_000; fn compare_crates(c: &mut Criterion) { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); let mut group = c.benchmark_group("Comparison"); for redundancy in [1, 5, 10, 20, 40] { let samples: Vec = (0..ITERS) - .map(|_| rng.gen_range(0..ITERS / redundancy)) + .map(|_| rng.random_range(0..ITERS / redundancy)) .collect(); group.bench_with_input( BenchmarkId::new("median_accumulator", redundancy), @@ -17,7 +17,7 @@ fn compare_crates(c: &mut Criterion) { b.iter(|| { let mut median = median_accumulator::vec::MedianAcc::new(); samples.iter().for_each(|s| median.push(*s)); - black_box(median.get_median()); + std::hint::black_box(median.get_median()); }) }, ); @@ -28,7 +28,7 @@ fn compare_crates(c: &mut Criterion) { b.iter(|| { let mut median = medianheap::MedianHeap::new(); samples.iter().for_each(|s| median.push(*s)); - black_box(median.median()); + std::hint::black_box(median.median()); }) }, ); diff --git a/src/lib.rs b/src/lib.rs index b742547..8c38a73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,13 @@ //! In doc comments, _N_ represents the number of samples, _D_ represents the number of different values taken by the samples. #![cfg_attr(not(feature = "std"), no_std)] +#![warn(missing_docs)] +#![deny(non_ascii_idents)] +#![deny(unnameable_types)] +#![deny(unreachable_pub)] +#![deny(unstable_features)] +#![warn(unused_qualifications)] +#![allow(clippy::tabs_in_doc_comments)] mod traits; @@ -34,25 +41,26 @@ pub struct MedianAcc< _t: core::marker::PhantomData, } +/// Aliases for `Vec` backend #[cfg(feature = "std")] pub mod vec { + /// Median accumulator using a `Vec` pub type MedianAcc = crate::MedianAcc>; } /// Computed median -/// -/// `Two` is when the median is the mean of the two values. -/// In this case, `result.0 < result.1`. #[derive(Clone, Debug, Eq, PartialEq)] pub enum MedianResult { + /// Median is an element from the list One(T), + /// Median is the mean of these two values from the list + /// + /// It is guaranteed that `result.0 < result.1`. Two(T, T), } -impl< - T: Clone + Ord, - V: DerefMut + cc_traits::VecMut<(T, u32)> + InsertIndex, - > MedianAcc +impl + cc_traits::VecMut<(T, u32)> + InsertIndex> + MedianAcc { /// Create an empty accumulator /// @@ -211,7 +219,7 @@ impl< mod tests { use super::*; - use rand::Rng; + use rand::RngExt; #[cfg(feature = "std")] fn naive_median(samples: &mut [T]) -> Option> { @@ -236,11 +244,11 @@ mod tests { #[cfg(feature = "std")] #[test] fn correctness() { - let mut rng = rand::thread_rng(); + let mut rng = rand::rng(); for _ in 0..100_000 { - let len: usize = rng.gen_range(0..100); - let mut samples: Vec = (0..len).map(|_| rng.gen_range(-100..100)).collect(); + let len: usize = rng.random_range(0..100); + let mut samples: Vec = (0..len).map(|_| rng.random_range(-100..100)).collect(); let mut median = vec::MedianAcc::new(); for sample in samples.iter() { diff --git a/src/traits.rs b/src/traits.rs index a5132b3..091c333 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,7 +1,9 @@ /// Collection where an item can be inserted at a given index. pub trait InsertIndex: cc_traits::Collection { + /// Output type of inserting at an index (may be `()`) type Output; + /// Insert `element` to the collection at `index` fn insert_index( &mut self, index: usize,