use oxmera_core::Shape;
use oxmera_tensor::tensor::Tensor;
fn empty(dims: &[usize]) -> Tensor {
Tensor::zeros(Shape::new(dims.to_vec()))
}
#[test]
fn sum_of_nothing_is_zero_for_every_empty_shape() {
for dims in [&[0usize][..], &[0, 3], &[2, 0], &[2, 0, 5], &[0, 0]] {
let t = empty(dims);
let all: Vec<usize> = (0..dims.len()).collect();
assert_eq!(
t.sum(&all).unwrap().to_vec_f32().unwrap(),
vec![0.0],
"{dims:?}"
);
}
}
#[test]
fn max_and_min_of_nothing_are_their_identities() {
let t = empty(&[0, 3]);
assert_eq!(
t.max(&[0, 1]).unwrap().to_vec_f32().unwrap(),
vec![f32::NEG_INFINITY]
);
assert_eq!(
t.min(&[0, 1]).unwrap().to_vec_f32().unwrap(),
vec![f32::INFINITY]
);
}
#[test]
fn reducing_only_the_empty_axis_keeps_the_others() {
let t = empty(&[2, 0, 3]);
let s = t.sum(&[1]).unwrap();
assert_eq!(s.dims(), &[2, 3]);
assert_eq!(s.to_vec_f32().unwrap(), vec![0.0; 6]);
let m = t.max_keepdim(&[1], true).unwrap();
assert_eq!(m.dims(), &[2, 1, 3]);
assert!(
m.to_vec_f32()
.unwrap()
.iter()
.all(|&x| x == f32::NEG_INFINITY)
);
}
#[test]
fn reducing_a_nonempty_axis_of_a_tensor_with_an_empty_one_gives_an_empty_result() {
let s = empty(&[2, 0, 3]).sum(&[2]).unwrap();
assert_eq!(s.dims(), &[2, 0]);
assert!(s.to_vec_f32().unwrap().is_empty());
}
#[test]
fn mean_of_nothing_is_a_typed_error() {
let err = empty(&[0, 3])
.mean(&[0, 1])
.expect_err("the mean of nothing is undefined and must not be a value");
let msg = err.to_string();
assert!(msg.contains("mean"), "the error must name the op: {msg}");
assert!(
msg.contains("extent 0") || msg.contains("0/0"),
"the error must say why: {msg}"
);
assert_eq!(
empty(&[0, 3]).sum(&[0, 1]).unwrap().to_vec_f32().unwrap(),
vec![0.0]
);
assert!(empty(&[0, 3]).max(&[0, 1]).unwrap().to_vec_f32().unwrap()[0] == f32::NEG_INFINITY);
let m = empty(&[0, 3]).mean(&[1]).unwrap();
assert_eq!(m.dims(), &[0]);
}
#[test]
fn softmax_over_an_empty_axis_is_empty() {
let s = empty(&[2, 0]).softmax(1).unwrap();
assert_eq!(s.dims(), &[2, 0]);
}
#[test]
fn argmax_over_an_empty_axis_is_an_error() {
let e = empty(&[2, 0]).argmax(1, false).unwrap_err().to_string();
assert!(e.contains("argmax"), "{e}");
assert_eq!(empty(&[2, 0]).argmax(0, false).unwrap().dims(), &[0]);
}
#[test]
fn elementwise_on_empty_is_unchanged() {
let t = empty(&[0, 3]);
assert_eq!(t.relu().unwrap().numel(), 0);
assert_eq!(t.add(&t).unwrap().numel(), 0);
assert_eq!(t.t().unwrap().contiguous().unwrap().dims(), &[3, 0]);
}