use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum AxisError {
#[error("axis {axis} is out of bounds for rank {rank}")]
OutOfBounds { axis: isize, rank: usize },
#[error("duplicate axis {axis}")]
Duplicate { axis: usize },
}
pub fn normalize_axis(axis: isize, rank: usize) -> Result<usize, AxisError> {
let normalized = if axis >= 0 {
axis as usize
} else {
rank.checked_sub(axis.unsigned_abs())
.ok_or(AxisError::OutOfBounds { axis, rank })?
};
if normalized >= rank {
return Err(AxisError::OutOfBounds { axis, rank });
}
Ok(normalized)
}
pub fn normalize_axes(axes: &[isize], rank: usize) -> Result<Vec<usize>, AxisError> {
let mut out = Vec::with_capacity(axes.len());
let mut seen = vec![false; rank];
for &axis in axes {
let normalized = normalize_axis(axis, rank)?;
if seen[normalized] {
return Err(AxisError::Duplicate { axis: normalized });
}
seen[normalized] = true;
out.push(normalized);
}
Ok(out)
}