#![cfg(feature = "ndarray")]
use ndarray::{s, Array2};
use rand::rngs::StdRng;
use rand::SeedableRng;
use smawk::{brute_force, online_column_minima, recursive};
mod random_monge;
use random_monge::random_monge_matrix;
#[test]
fn column_minima_agree() {
let sizes = [1, 2, 3, 4, 5, 10, 15, 20, 30];
let mut rng = StdRng::seed_from_u64(0);
for _ in 0..4 {
for &m in &sizes {
for &n in &sizes {
let matrix: Array2<i32> = random_monge_matrix(m, n, &mut rng);
let brute_force = brute_force::row_minima(&matrix);
let recursive = recursive::row_minima(&matrix);
let smawk = smawk::row_minima(&matrix);
assert_eq!(
brute_force, recursive,
"recursive and brute force differs on:\n{:?}",
matrix
);
assert_eq!(
brute_force, smawk,
"SMAWK and brute force differs on:\n{:?}",
matrix
);
let brute_force = brute_force::column_minima(&matrix);
let recursive = recursive::column_minima(&matrix);
let smawk = smawk::column_minima(&matrix);
assert_eq!(
brute_force, recursive,
"recursive and brute force differs on:\n{:?}",
matrix
);
assert_eq!(
brute_force, smawk,
"SMAWK and brute force differs on:\n{:?}",
matrix
);
}
}
}
}
#[test]
fn online_agree() {
let sizes = [1, 2, 3, 4, 5, 10, 15, 20, 30, 50];
let mut rng = StdRng::seed_from_u64(0);
for _ in 0..5 {
for &size in &sizes {
let mut matrix: Array2<i32> = random_monge_matrix(size, size, &mut rng);
let max = *matrix.iter().max().unwrap_or(&0);
for idx in 0..(size as isize) {
matrix.slice_mut(s![idx..idx + 1, ..idx + 1]).fill(max);
}
let initial = 42;
matrix.slice_mut(s![0.., ..1]).fill(initial);
let brute_force = brute_force::column_minima(&matrix)
.iter()
.enumerate()
.map(|(j, &i)| (i, matrix[[i, j]]))
.collect::<Vec<_>>();
let online = online_column_minima(initial, size, |_, i, j| matrix[[i, j]]);
assert_eq!(
brute_force, online,
"brute force and online differ on:\n{:3?}",
matrix
);
}
}
}
#[test]
fn unbalanced_matrices_agree() {
let mut rng = StdRng::seed_from_u64(42);
let cases = [(1, 100), (100, 1), (2, 50), (50, 2), (5, 80), (80, 5)];
for &(m, n) in &cases {
let matrix: Array2<i32> = random_monge_matrix(m, n, &mut rng);
let brute_force = brute_force::row_minima(&matrix);
let recursive = recursive::row_minima(&matrix);
let smawk = smawk::row_minima(&matrix);
assert_eq!(brute_force, recursive);
assert_eq!(brute_force, smawk);
let brute_force = brute_force::column_minima(&matrix);
let recursive = recursive::column_minima(&matrix);
let smawk = smawk::column_minima(&matrix);
assert_eq!(brute_force, recursive);
assert_eq!(brute_force, smawk);
}
}
#[test]
fn empty_matrices_agree() {
let matrix: Array2<i32> = Array2::from_elem((0, 0), 0);
let brute_force_row = brute_force::row_minima(&matrix);
let recursive_row = recursive::row_minima(&matrix);
let smawk_row = smawk::row_minima(&matrix);
assert_eq!(brute_force_row, recursive_row);
assert_eq!(brute_force_row, smawk_row);
assert_eq!(brute_force_row, vec![]);
let brute_force_col = brute_force::column_minima(&matrix);
let recursive_col = recursive::column_minima(&matrix);
let smawk_col = smawk::column_minima(&matrix);
assert_eq!(brute_force_col, recursive_col);
assert_eq!(brute_force_col, smawk_col);
assert_eq!(brute_force_col, vec![]);
}
#[test]
#[should_panic]
fn smawk_row_minima_empty_cols_panics() {
let matrix: Array2<i32> = Array2::from_elem((5, 0), 0);
smawk::row_minima(&matrix);
}
#[test]
#[should_panic]
fn brute_force_row_minima_empty_cols_panics() {
let matrix: Array2<i32> = Array2::from_elem((5, 0), 0);
brute_force::row_minima(&matrix);
}
#[test]
#[should_panic]
fn recursive_row_minima_empty_cols_panics() {
let matrix: Array2<i32> = Array2::from_elem((5, 0), 0);
recursive::row_minima(&matrix);
}
#[test]
#[should_panic]
fn smawk_column_minima_empty_rows_panics() {
let matrix: Array2<i32> = Array2::from_elem((0, 5), 0);
smawk::column_minima(&matrix);
}
#[test]
#[should_panic]
fn brute_force_column_minima_empty_rows_panics() {
let matrix: Array2<i32> = Array2::from_elem((0, 5), 0);
brute_force::column_minima(&matrix);
}
#[test]
#[should_panic]
fn recursive_column_minima_empty_rows_panics() {
let matrix: Array2<i32> = Array2::from_elem((0, 5), 0);
recursive::column_minima(&matrix);
}