use alloc::vec::Vec;
use core::cmp::Ordering;
use crate::dynmatrix::DynMatrix;
use crate::traits::FloatScalar;
use super::resize::resize_bilinear;
pub fn median_pool<T: FloatScalar>(src: &DynMatrix<T>, block_size: usize) -> DynMatrix<T> {
assert!(block_size > 0, "block_size must be positive");
let h_in = src.nrows();
let w_in = src.ncols();
if h_in == 0 || w_in == 0 {
return DynMatrix::<T>::zeros(0, 0);
}
let h_out = h_in.div_ceil(block_size);
let w_out = w_in.div_ceil(block_size);
let mut dst = DynMatrix::<T>::zeros(h_out, w_out);
let mut buf: Vec<T> = Vec::with_capacity(block_size * block_size);
for bj in 0..w_out {
let j0 = bj * block_size;
let j1 = (j0 + block_size).min(w_in);
for bi in 0..h_out {
let i0 = bi * block_size;
let i1 = (i0 + block_size).min(h_in);
buf.clear();
for j in j0..j1 {
for i in i0..i1 {
buf.push(src[(i, j)]);
}
}
let mid = buf.len() / 2;
buf.select_nth_unstable_by(mid, |a, b| {
a.partial_cmp(b).unwrap_or(Ordering::Equal)
});
dst[(bi, bj)] = buf[mid];
}
}
dst
}
pub fn median_pool_upsampled<T: FloatScalar>(
src: &DynMatrix<T>,
block_size: usize,
) -> DynMatrix<T> {
let pooled = median_pool(src, block_size);
resize_bilinear(&pooled, src.nrows(), src.ncols())
}