From 1b6a04ca5504955c571d1c97504fb45ea0befee4 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Mon, 8 Jan 2024 01:21:28 +0400 Subject: Initial vendor packages Signed-off-by: Valentin Popov --- vendor/smawk/src/brute_force.rs | 150 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 vendor/smawk/src/brute_force.rs (limited to 'vendor/smawk/src/brute_force.rs') diff --git a/vendor/smawk/src/brute_force.rs b/vendor/smawk/src/brute_force.rs new file mode 100644 index 0000000..1ec0ca3 --- /dev/null +++ b/vendor/smawk/src/brute_force.rs @@ -0,0 +1,150 @@ +//! Brute-force algorithm for finding column minima. +//! +//! The functions here are mostly meant to be used for testing +//! correctness of the SMAWK implementation. +//! +//! **Note: this module is only available if you enable the `ndarray` +//! Cargo feature.** + +use ndarray::{Array2, ArrayView1}; + +/// Compute lane minimum by brute force. +/// +/// This does a simple scan through the lane (row or column). +#[inline] +pub fn lane_minimum(lane: ArrayView1<'_, T>) -> usize { + lane.iter() + .enumerate() + .min_by_key(|&(idx, elem)| (elem, idx)) + .map(|(idx, _)| idx) + .expect("empty lane in matrix") +} + +/// Compute row minima by brute force in O(*mn*) time. +/// +/// This function implements a simple brute-force approach where each +/// matrix row is scanned completely. This means that the function +/// works on all matrices, not just Monge matrices. +/// +/// # Examples +/// +/// ``` +/// let matrix = ndarray::arr2(&[[4, 2, 4, 3], +/// [5, 3, 5, 3], +/// [5, 3, 3, 1]]); +/// assert_eq!(smawk::brute_force::row_minima(&matrix), +/// vec![1, 1, 3]); +/// ``` +/// +/// # Panics +/// +/// It is an error to call this on a matrix with zero columns. +pub fn row_minima(matrix: &Array2) -> Vec { + matrix.rows().into_iter().map(lane_minimum).collect() +} + +/// Compute column minima by brute force in O(*mn*) time. +/// +/// This function implements a simple brute-force approach where each +/// matrix column is scanned completely. This means that the function +/// works on all matrices, not just Monge matrices. +/// +/// # Examples +/// +/// ``` +/// let matrix = ndarray::arr2(&[[4, 2, 4, 3], +/// [5, 3, 5, 3], +/// [5, 3, 3, 1]]); +/// assert_eq!(smawk::brute_force::column_minima(&matrix), +/// vec![0, 0, 2, 2]); +/// ``` +/// +/// # Panics +/// +/// It is an error to call this on a matrix with zero rows. +pub fn column_minima(matrix: &Array2) -> Vec { + matrix.columns().into_iter().map(lane_minimum).collect() +} + +#[cfg(test)] +mod tests { + use super::*; + use ndarray::arr2; + + #[test] + fn brute_force_1x1() { + let matrix = arr2(&[[2]]); + let minima = vec![0]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_2x1() { + let matrix = arr2(&[ + [3], // + [2], + ]); + let minima = vec![0, 0]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_1x2() { + let matrix = arr2(&[[2, 1]]); + let minima = vec![1]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_2x2() { + let matrix = arr2(&[ + [3, 2], // + [2, 1], + ]); + let minima = vec![1, 1]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_3x3() { + let matrix = arr2(&[ + [3, 4, 4], // + [3, 4, 4], + [2, 3, 3], + ]); + let minima = vec![0, 0, 0]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_4x4() { + let matrix = arr2(&[ + [4, 5, 5, 5], // + [2, 3, 3, 3], + [2, 3, 3, 3], + [2, 2, 2, 2], + ]); + let minima = vec![0, 0, 0, 0]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } + + #[test] + fn brute_force_5x5() { + let matrix = arr2(&[ + [3, 2, 4, 5, 6], + [2, 1, 3, 3, 4], + [2, 1, 3, 3, 4], + [3, 2, 4, 3, 4], + [4, 3, 2, 1, 1], + ]); + let minima = vec![1, 1, 1, 1, 3]; + assert_eq!(row_minima(&matrix), minima); + assert_eq!(column_minima(&matrix.reversed_axes()), minima); + } +} -- cgit v1.2.3