use numrs2::array::Array;
use numrs2::stride_tricks::{as_strided, broadcast_arrays, broadcast_to, sliding_window_view};
#[test]
fn as_strided_doc_example_subsamples_corners() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(&[3, 3]);
let strided = as_strided(&array, &[2, 2], &[6, 2]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![2, 2]);
assert_eq!(strided.to_vec(), vec![1, 3, 7, 9]);
}
#[test]
fn as_strided_literal_two_two_strides_are_element_offsets() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(&[3, 3]);
let strided = as_strided(&array, &[2, 2], &[2, 2]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![2, 2]);
assert_eq!(strided.to_vec(), vec![1, 3, 3, 5]);
}
#[test]
fn as_strided_overlapping_windows_from_1d() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5]);
let strided = as_strided(&array, &[4, 2], &[1, 1]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![4, 2]);
assert_eq!(strided.to_vec(), vec![1, 2, 2, 3, 3, 4, 4, 5]);
}
#[test]
fn as_strided_stride_zero_repeats_row() {
let array = Array::from_vec(vec![10, 20, 30]);
let strided = as_strided(&array, &[3, 3], &[0, 1]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![3, 3]);
assert_eq!(strided.to_vec(), vec![10, 20, 30, 10, 20, 30, 10, 20, 30]);
}
#[test]
fn as_strided_degenerate_dimension_stride_is_dont_care() {
let array = Array::from_vec(vec![1, 2, 3]);
let strided = as_strided(&array, &[1, 3], &[-5, 1]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![1, 3]);
assert_eq!(strided.to_vec(), vec![1, 2, 3]);
}
#[test]
fn as_strided_positive_bounds_violation_returns_err() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5]);
let result = as_strided(&array, &[10], &[1]);
assert!(result.is_err());
}
#[test]
fn as_strided_negative_bounds_violation_returns_err() {
let array = Array::from_vec(vec![1, 2, 3]);
let result = as_strided(&array, &[5], &[-1]);
assert!(result.is_err());
}
#[test]
fn as_strided_dimension_mismatch_returns_err() {
let array = Array::from_vec(vec![1, 2, 3, 4]).reshape(&[2, 2]);
let result = as_strided(&array, &[2, 2], &[1]);
assert!(result.is_err());
}
#[test]
fn as_strided_zero_size_output_returns_empty() {
let array = Array::from_vec(vec![1, 2, 3]);
let strided = as_strided(&array, &[0, 3], &[1, 1]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![0, 3]);
assert_eq!(strided.to_vec(), Vec::<i32>::new());
}
#[test]
fn as_strided_3d_subsamples_planes() {
let array = Array::from_vec((1..=24).collect::<Vec<i32>>());
let strided = as_strided(&array, &[2, 3, 2], &[12, 2, 1]).expect("as_strided should succeed");
assert_eq!(strided.shape(), vec![2, 3, 2]);
assert_eq!(
strided.to_vec(),
vec![1, 2, 3, 4, 5, 6, 13, 14, 15, 16, 17, 18]
);
}
#[test]
fn sliding_window_view_1d_matches_reference() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5]);
let windows =
sliding_window_view(&array, &[2], None).expect("sliding_window_view should succeed");
assert_eq!(windows.shape(), vec![4, 2]);
assert_eq!(windows.to_vec(), vec![1, 2, 2, 3, 3, 4, 4, 5]);
}
#[test]
fn sliding_window_view_1d_with_step() {
let array = Array::from_vec((1..=7).collect::<Vec<i32>>());
let windows =
sliding_window_view(&array, &[2], Some(&[2])).expect("sliding_window_view should succeed");
assert_eq!(windows.shape(), vec![3, 2]);
assert_eq!(windows.to_vec(), vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn sliding_window_view_2d_matches_numpy_docs() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(&[3, 3]);
let windows =
sliding_window_view(&array, &[2, 2], None).expect("sliding_window_view should succeed");
assert_eq!(windows.shape(), vec![2, 2, 2, 2]);
assert_eq!(
windows.to_vec(),
vec![1, 2, 4, 5, 2, 3, 5, 6, 4, 5, 7, 8, 5, 6, 8, 9]
);
}
#[test]
fn sliding_window_view_3d_hand_computed() {
let array = Array::from_vec((1..=12).collect::<Vec<i32>>()).reshape(&[3, 2, 2]);
let windows =
sliding_window_view(&array, &[2, 2, 2], None).expect("sliding_window_view should succeed");
assert_eq!(windows.shape(), vec![2, 1, 1, 2, 2, 2]);
assert_eq!(
windows.to_vec(),
vec![1, 2, 3, 4, 5, 6, 7, 8, 5, 6, 7, 8, 9, 10, 11, 12]
);
}
#[test]
fn sliding_window_view_errors_when_window_exceeds_dim() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(&[3, 3]);
let result = sliding_window_view(&array, &[4, 2], None);
assert!(result.is_err());
}
#[test]
fn sliding_window_view_errors_on_window_ndim_mismatch() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5, 6, 7, 8, 9]).reshape(&[3, 3]);
let result = sliding_window_view(&array, &[2], None);
assert!(result.is_err());
}
#[test]
fn sliding_window_view_errors_on_zero_step_instead_of_panicking() {
let array = Array::from_vec(vec![1, 2, 3, 4, 5]);
let result = sliding_window_view(&array, &[2], Some(&[0]));
assert!(result.is_err());
}
#[test]
fn broadcast_to_row_vector_replicates_values() {
let array = Array::from_vec(vec![1, 2, 3]).reshape(&[1, 3]);
let result = broadcast_to(&array, &[3, 3]).expect("broadcast_to should succeed");
assert_eq!(result.shape(), vec![3, 3]);
assert_eq!(result.to_vec(), vec![1, 2, 3, 1, 2, 3, 1, 2, 3]);
}
#[test]
fn broadcast_to_column_vector_replicates_values() {
let array = Array::from_vec(vec![4, 5, 6]).reshape(&[3, 1]);
let result = broadcast_to(&array, &[3, 3]).expect("broadcast_to should succeed");
assert_eq!(result.shape(), vec![3, 3]);
assert_eq!(result.to_vec(), vec![4, 4, 4, 5, 5, 5, 6, 6, 6]);
}
#[test]
fn broadcast_arrays_outer_pattern_matches_numpy() {
let a = Array::from_vec(vec![1, 2, 3]).reshape(&[1, 3]);
let b = Array::from_vec(vec![4, 5, 6]).reshape(&[3, 1]);
let result = broadcast_arrays(&[&a, &b]).expect("broadcast_arrays should succeed");
assert_eq!(result.len(), 2);
assert_eq!(result[0].shape(), vec![3, 3]);
assert_eq!(result[1].shape(), vec![3, 3]);
assert_eq!(result[0].to_vec(), vec![1, 2, 3, 1, 2, 3, 1, 2, 3]);
assert_eq!(result[1].to_vec(), vec![4, 4, 4, 5, 5, 5, 6, 6, 6]);
}