use crate::dynmatrix::DynMatrix;
use crate::traits::{FloatScalar, MatrixRef};
pub fn integral_image<T: FloatScalar>(src: &DynMatrix<T>) -> DynMatrix<T> {
let h = src.nrows();
let w = src.ncols();
let mut sat = DynMatrix::<T>::zeros(h + 1, w + 1);
for i in 0..h {
let mut row_sum = T::zero();
for j in 0..w {
row_sum = row_sum + *src.get(i, j);
let above = sat[(i, j + 1)];
sat[(i + 1, j + 1)] = above + row_sum;
}
}
sat
}
pub(crate) fn integral_image_with_squares<T: FloatScalar>(
src: &DynMatrix<T>,
) -> (DynMatrix<T>, DynMatrix<T>) {
let h = src.nrows();
let w = src.ncols();
let mut sat = DynMatrix::<T>::zeros(h + 1, w + 1);
let mut sat2 = DynMatrix::<T>::zeros(h + 1, w + 1);
for i in 0..h {
let mut row_sum = T::zero();
let mut row_sum2 = T::zero();
for j in 0..w {
let v = *src.get(i, j);
row_sum = row_sum + v;
row_sum2 = row_sum2 + v * v;
sat[(i + 1, j + 1)] = sat[(i, j + 1)] + row_sum;
sat2[(i + 1, j + 1)] = sat2[(i, j + 1)] + row_sum2;
}
}
(sat, sat2)
}
#[inline]
pub fn integral_rect_sum<T: FloatScalar>(
sat: &DynMatrix<T>,
r0: usize,
c0: usize,
r1: usize,
c1: usize,
) -> T {
debug_assert!(r0 <= r1 && c0 <= c1, "rectangle bounds must be ordered");
let nrows = sat.nrows().saturating_sub(1);
let ncols = sat.ncols().saturating_sub(1);
let r0 = r0.min(nrows);
let c0 = c0.min(ncols);
let r1 = r1.min(nrows);
let c1 = c1.min(ncols);
sat[(r1, c1)] + sat[(r0, c0)] - sat[(r1, c0)] - sat[(r0, c1)]
}