use num_traits::Float;
#[derive(Copy, Clone, Debug)]
pub struct Window {
pub left: usize,
pub right: usize,
}
impl Window {
#[inline]
pub fn initialize(idx: usize, window_size: usize, n: usize) -> Self {
debug_assert!(
window_size >= 1,
"initialize_window: window_size must be at least 1"
);
if window_size >= n {
return Self {
left: 0,
right: n.saturating_sub(1),
};
}
let half = window_size / 2;
let mut left = idx.saturating_sub(half);
let max_left = n - window_size;
if left > max_left {
left = max_left;
}
let right = left + window_size - 1;
Self { left, right }
}
#[inline]
pub fn recenter<T: Float>(&mut self, x: &[T], current: usize, n: usize) {
debug_assert!(current < n, "recenter: current index out of bounds");
self.left = self.left.min(n - 1);
self.right = self.right.min(n - 1);
let x_current = x[current];
while self.right < n - 1 {
let d_left = x_current - x[self.left];
let d_right = x[self.right + 1] - x_current;
if d_left <= d_right {
break;
}
self.left += 1;
self.right += 1;
}
while self.left > 0 {
let d_left = x_current - x[self.left - 1];
let d_right = x[self.right] - x_current;
if d_right <= d_left {
break;
}
self.left -= 1;
self.right -= 1;
}
}
#[inline]
pub fn calculate_span<T: Float>(n: usize, frac: T) -> usize {
let epsilon = T::from(1e-5).unwrap();
let frac_n = frac * T::from(n).unwrap() + epsilon;
let frac_n_int = frac_n.to_usize().unwrap_or(0);
usize::max(2, usize::min(n, frac_n_int))
}
#[allow(dead_code)]
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn len(&self) -> usize {
self.right - self.left + 1
}
}