use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Error)]
pub enum ReductionShapeError {
#[error("axis {axis} is out of bounds for rank {rank}")]
AxisOutOfBounds { axis: usize, rank: usize },
#[error("duplicate axis {axis}")]
DuplicateAxis { axis: usize },
}
pub fn reduced_shape(
input_shape: &[usize],
axes: &[usize],
keepdims: bool,
) -> Result<Vec<usize>, ReductionShapeError> {
let mut reduced = vec![false; input_shape.len()];
for &axis in axes {
if axis >= input_shape.len() {
return Err(ReductionShapeError::AxisOutOfBounds {
axis,
rank: input_shape.len(),
});
}
if reduced[axis] {
return Err(ReductionShapeError::DuplicateAxis { axis });
}
reduced[axis] = true;
}
let mut out = Vec::with_capacity(input_shape.len());
for (axis, &dim) in input_shape.iter().enumerate() {
if reduced[axis] {
if keepdims {
out.push(1);
}
} else {
out.push(dim);
}
}
Ok(out)
}