From 305e89d5368a9d17672bdb5a0d0010648c7ac303 Mon Sep 17 00:00:00 2001 From: David Peter Date: Mon, 5 Oct 2026 10:00:07 +0200 Subject: [PATCH] Consolidate min and max in the statistics module --- src/benchmark/mod.rs | 7 +++---- src/util/min_max.rs | 28 ---------------------------- src/util/mod.rs | 1 - src/util/statistics.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 33 deletions(-) delete mode 100644 src/util/min_max.rs diff --git a/src/benchmark/mod.rs b/src/benchmark/mod.rs index 0ba58a6..fd59224 100644 --- a/src/benchmark/mod.rs +++ b/src/benchmark/mod.rs @@ -19,8 +19,7 @@ use crate::output::progress_bar::get_progress_bar; use crate::output::warnings::{OutlierWarningOptions, Warnings}; use crate::parameter::ParameterNameAndValue; use crate::util::exit_code::extract_exit_code; -use crate::util::min_max::{max, min}; -use crate::util::statistics::{mean, median, standard_deviation}; +use crate::util::statistics::{max, mean, median, min, standard_deviation}; use crate::util::units::Second; use benchmark_result::BenchmarkResult; use measurement::Measurement; @@ -344,8 +343,8 @@ impl<'a> Benchmark<'a> { None }; let t_median = median(×_real); - let t_min = min(×_real); - let t_max = max(×_real); + let t_min = min(times_real.iter().copied()); + let t_max = max(times_real.iter().copied()); let user_mean = mean(×_user); let system_mean = mean(×_system); diff --git a/src/util/min_max.rs b/src/util/min_max.rs deleted file mode 100644 index d4ee07e..0000000 --- a/src/util/min_max.rs +++ /dev/null @@ -1,28 +0,0 @@ -/// A max function for f64's without NaNs -pub fn max(vals: &[f64]) -> f64 { - *vals - .iter() - .max_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap() -} - -/// A min function for f64's without NaNs -pub fn min(vals: &[f64]) -> f64 { - *vals - .iter() - .min_by(|a, b| a.partial_cmp(b).unwrap()) - .unwrap() -} - -#[test] -fn test_max() { - let assert_float_eq = |a: f64, b: f64| { - assert!((a - b).abs() < f64::EPSILON); - }; - - assert_float_eq(1.0, max(&[1.0])); - assert_float_eq(-1.0, max(&[-1.0])); - assert_float_eq(-1.0, max(&[-2.0, -1.0])); - assert_float_eq(1.0, max(&[-1.0, 1.0])); - assert_float_eq(1.0, max(&[-1.0, 1.0, 0.0])); -} diff --git a/src/util/mod.rs b/src/util/mod.rs index 8996214..e5cdaba 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,5 +1,4 @@ pub mod exit_code; -pub mod min_max; pub mod number; pub mod randomized_environment_offset; pub mod statistics; diff --git a/src/util/statistics.rs b/src/util/statistics.rs index 185233b..1099caa 100644 --- a/src/util/statistics.rs +++ b/src/util/statistics.rs @@ -1,5 +1,21 @@ //! Statistics for non-empty samples of finite measurements. +/// A min function that assumes no NaNs and at least one element +pub fn min(values: impl IntoIterator) -> Q { + values + .into_iter() + .min_by(|a, b| a.partial_cmp(b).expect("No NaN values")) + .expect("'min' requires at least one element") +} + +/// A max function that assumes no NaNs and at least one element +pub fn max(values: impl IntoIterator) -> Q { + values + .into_iter() + .max_by(|a, b| a.partial_cmp(b).expect("No NaN values")) + .expect("'max' requires at least one element") +} + /// Arithmetic mean, summing measurements in their original order. pub fn mean(values: &[f64]) -> f64 { values.iter().fold(0.0, |sum, value| sum + value) / values.len() as f64 @@ -44,6 +60,30 @@ mod tests { use super::*; use approx::assert_relative_eq; + #[test] + fn test_min() { + assert_eq!(1.0, min([1.0])); + assert_eq!(-1.0, min([-1.0])); + assert_eq!(-2.0, min([-2.0, -1.0])); + assert_eq!(-1.0, min([-1.0, 1.0])); + assert_eq!(-1.0, min([1.0, -1.0, 0.0])); + + let values = vec![1024.0, 2.0, 3.0]; + assert_eq!(*min(&values), 2.0); + } + + #[test] + fn test_max() { + assert_eq!(1.0, max([1.0])); + assert_eq!(-1.0, max([-1.0])); + assert_eq!(-1.0, max([-2.0, -1.0])); + assert_eq!(1.0, max([-1.0, 1.0])); + assert_eq!(1.0, max([-1.0, 1.0, 0.0])); + + let values = vec![1.0, 2048.0, 3.0]; + assert_eq!(*max(&values), 2048.0); + } + #[test] fn test_mean() { assert_eq!(1.0, mean(&[1.0]));