aboutsummaryrefslogtreecommitdiff
path: root/vendor/smawk/src/recursive.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/smawk/src/recursive.rs')
-rw-r--r--vendor/smawk/src/recursive.rs191
1 files changed, 0 insertions, 191 deletions
diff --git a/vendor/smawk/src/recursive.rs b/vendor/smawk/src/recursive.rs
deleted file mode 100644
index 9df8b9c..0000000
--- a/vendor/smawk/src/recursive.rs
+++ /dev/null
@@ -1,191 +0,0 @@
-//! Recursive 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::{s, Array2, ArrayView2, Axis};
-
-/// Compute row minima in O(*m* + *n* log *m*) time.
-///
-/// This function computes row minima in a totally monotone matrix
-/// using a recursive algorithm.
-///
-/// Running time on an *m* ✕ *n* matrix: O(*m* + *n* log *m*).
-///
-/// # Examples
-///
-/// ```
-/// let matrix = ndarray::arr2(&[[4, 2, 4, 3],
-/// [5, 3, 5, 3],
-/// [5, 3, 3, 1]]);
-/// assert_eq!(smawk::recursive::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<T: Ord>(matrix: &Array2<T>) -> Vec<usize> {
- let mut minima = vec![0; matrix.nrows()];
- recursive_inner(matrix.view(), &|| Direction::Row, 0, &mut minima);
- minima
-}
-
-/// Compute column minima in O(*n* + *m* log *n*) time.
-///
-/// This function computes column minima in a totally monotone matrix
-/// using a recursive algorithm.
-///
-/// Running time on an *m* ✕ *n* matrix: O(*n* + *m* log *n*).
-///
-/// # Examples
-///
-/// ```
-/// let matrix = ndarray::arr2(&[[4, 2, 4, 3],
-/// [5, 3, 5, 3],
-/// [5, 3, 3, 1]]);
-/// assert_eq!(smawk::recursive::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<T: Ord>(matrix: &Array2<T>) -> Vec<usize> {
- let mut minima = vec![0; matrix.ncols()];
- recursive_inner(matrix.view(), &|| Direction::Column, 0, &mut minima);
- minima
-}
-
-/// The type of minima (row or column) we compute.
-enum Direction {
- Row,
- Column,
-}
-
-/// Compute the minima along the given direction (`Direction::Row` for
-/// row minima and `Direction::Column` for column minima).
-///
-/// The direction is given as a generic function argument to allow
-/// monomorphization to kick in. The function calls will be inlined
-/// and optimized away and the result is that the compiler generates
-/// differnet code for finding row and column minima.
-fn recursive_inner<T: Ord, F: Fn() -> Direction>(
- matrix: ArrayView2<'_, T>,
- dir: &F,
- offset: usize,
- minima: &mut [usize],
-) {
- if matrix.is_empty() {
- return;
- }
-
- let axis = match dir() {
- Direction::Row => Axis(0),
- Direction::Column => Axis(1),
- };
- let mid = matrix.len_of(axis) / 2;
- let min_idx = crate::brute_force::lane_minimum(matrix.index_axis(axis, mid));
- minima[mid] = offset + min_idx;
-
- if mid == 0 {
- return; // Matrix has a single row or column, so we're done.
- }
-
- let top_left = match dir() {
- Direction::Row => matrix.slice(s![..mid, ..(min_idx + 1)]),
- Direction::Column => matrix.slice(s![..(min_idx + 1), ..mid]),
- };
- let bot_right = match dir() {
- Direction::Row => matrix.slice(s![(mid + 1).., min_idx..]),
- Direction::Column => matrix.slice(s![min_idx.., (mid + 1)..]),
- };
- recursive_inner(top_left, dir, offset, &mut minima[..mid]);
- recursive_inner(bot_right, dir, offset + min_idx, &mut minima[mid + 1..]);
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use ndarray::arr2;
-
- #[test]
- fn recursive_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 recursive_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 recursive_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 recursive_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 recursive_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 recursive_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 recursive_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);
- }
-}