use approx::assert_relative_eq;
use numrs2::array::Array;
use numrs2::math::{arange, linspace, ElementWiseMath};
use numrs2::prelude::*;
use numrs2::simd::simd_add;
use numrs2::ufuncs::{cos, sin, tan};
#[cfg(test)]
mod array_creation_tests {
use super::*;
#[test]
fn test_zeros_creation() {
let arr1d = Array::<f64>::zeros(&[5]);
assert_eq!(arr1d.shape(), vec![5]);
assert_eq!(arr1d.size(), 5);
assert_eq!(arr1d.ndim(), 1);
assert!(arr1d.to_vec().iter().all(|&x| x == 0.0));
let arr2d = Array::<f64>::zeros(&[3, 4]);
assert_eq!(arr2d.shape(), vec![3, 4]);
assert_eq!(arr2d.size(), 12);
assert_eq!(arr2d.ndim(), 2);
assert!(arr2d.to_vec().iter().all(|&x| x == 0.0));
let arr3d = Array::<f64>::zeros(&[2, 3, 4]);
assert_eq!(arr3d.shape(), vec![2, 3, 4]);
assert_eq!(arr3d.size(), 24);
assert_eq!(arr3d.ndim(), 3);
assert!(arr3d.to_vec().iter().all(|&x| x == 0.0));
let arr_i32 = Array::<i32>::zeros(&[3, 3]);
assert!(arr_i32.to_vec().iter().all(|&x| x == 0));
let arr_f32 = Array::<f32>::zeros(&[2, 2]);
assert!(arr_f32.to_vec().iter().all(|&x| x == 0.0));
}
#[test]
fn test_ones_creation() {
let arr1d = Array::<f64>::ones(&[4]);
assert_eq!(arr1d.shape(), vec![4]);
assert!(arr1d.to_vec().iter().all(|&x| x == 1.0));
let arr2d = Array::<f64>::ones(&[2, 3]);
assert_eq!(arr2d.shape(), vec![2, 3]);
assert!(arr2d.to_vec().iter().all(|&x| x == 1.0));
let arr_i32 = Array::<i32>::ones(&[3, 2]);
assert!(arr_i32.to_vec().iter().all(|&x| x == 1));
}
#[test]
fn test_full_creation() {
let arr_f64 = Array::<f64>::full(&[3, 2], 5.5);
assert_eq!(arr_f64.shape(), vec![3, 2]);
assert!(arr_f64.to_vec().iter().all(|&x| x == 5.5));
let arr_i32 = Array::<i32>::full(&[2, 2], -10);
assert!(arr_i32.to_vec().iter().all(|&x| x == -10));
}
#[test]
fn test_from_vec_creation() {
let data = vec![1.0, 2.0, 3.0, 4.0];
let arr = Array::from_vec(data.clone());
assert_eq!(arr.shape(), vec![4]);
assert_eq!(arr.to_vec(), data);
let int_data = vec![1, 2, 3, 4, 5];
let int_arr = Array::from_vec(int_data.clone());
assert_eq!(int_arr.to_vec(), int_data);
}
#[test]
fn test_arange_creation() {
let arr = arange(0.0, 5.0, 1.0);
assert_eq!(arr.size(), 5);
assert_eq!(arr.to_vec(), vec![0.0, 1.0, 2.0, 3.0, 4.0]);
let arr_neg = arange(5.0, 0.0, -1.0);
assert_eq!(arr_neg.to_vec(), vec![5.0, 4.0, 3.0, 2.0, 1.0]);
let arr_frac = arange(0.0, 3.0, 0.5);
assert_eq!(arr_frac.size(), 6);
for (i, &val) in arr_frac.to_vec().iter().enumerate() {
assert_relative_eq!(val, i as f64 * 0.5, epsilon = 1e-10);
}
}
#[test]
fn test_linspace_creation() {
let arr = linspace(0.0, 10.0, 11);
assert_eq!(arr.size(), 11);
for (i, &val) in arr.to_vec().iter().enumerate() {
assert_relative_eq!(val, i as f64, epsilon = 1e-10);
}
let arr2 = linspace(-1.0, 1.0, 5);
let expected = [-1.0, -0.5, 0.0, 0.5, 1.0];
for (actual, &expected) in arr2.to_vec().iter().zip(expected.iter()) {
assert_relative_eq!(*actual, expected, epsilon = 1e-10);
}
}
#[test]
fn test_empty_array_creation() {
let arr = Array::<f64>::zeros(&[0]);
assert_eq!(arr.shape(), vec![0]);
assert_eq!(arr.size(), 0);
assert_eq!(arr.to_vec().len(), 0);
let arr2d = Array::<f64>::zeros(&[0, 5]);
assert_eq!(arr2d.shape(), vec![0, 5]);
assert_eq!(arr2d.size(), 0);
}
}
#[cfg(test)]
mod array_manipulation_tests {
use super::*;
#[test]
fn test_reshape_operations() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let arr = Array::from_vec(data);
let reshaped = arr.reshape(&[2, 3]);
assert_eq!(reshaped.shape(), vec![2, 3]);
assert_eq!(reshaped.size(), 6);
let reshaped2 = arr.reshape(&[3, 2]);
assert_eq!(reshaped2.shape(), vec![3, 2]);
let reshaped3d = arr.reshape(&[1, 2, 3]);
assert_eq!(reshaped3d.shape(), vec![1, 2, 3]);
assert_eq!(reshaped3d.ndim(), 3);
let flat = reshaped.reshape(&[6]);
assert_eq!(flat.shape(), vec![6]);
assert_eq!(flat.ndim(), 1);
}
#[test]
fn test_transpose_operations() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let arr = Array::from_vec(data).reshape(&[2, 3]);
let transposed = arr.transpose();
assert_eq!(transposed.shape(), vec![3, 2]);
let orig_vec = arr.to_vec();
let trans_vec = transposed.to_vec();
for &val in &orig_vec {
assert!(
trans_vec.contains(&val),
"Missing value {} after transpose",
val
);
}
let arr1d = Array::from_vec(vec![1.0, 2.0, 3.0]);
let trans1d = arr1d.transpose();
assert_eq!(trans1d.shape(), vec![3]);
}
#[test]
fn test_flatten_operations() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let arr = Array::from_vec(data.clone()).reshape(&[2, 3]);
let flattened = arr.flatten(None);
assert_eq!(flattened.shape(), vec![6]);
assert_eq!(flattened.size(), 6);
let flat_vec = flattened.to_vec();
assert_eq!(flat_vec.len(), 6);
for &val in &data {
assert!(
flat_vec.contains(&val),
"Missing value {} after flatten",
val
);
}
}
#[test]
fn test_squeeze_operations() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0]).reshape(&[1, 3, 1]);
assert_eq!(arr.shape(), vec![1, 3, 1]);
let squeezed = squeeze(&arr, None).unwrap();
assert_eq!(squeezed.shape(), vec![3]);
assert_eq!(squeezed.to_vec(), vec![1.0, 2.0, 3.0]);
let squeezed_axis0 = squeeze(&arr, Some(0)).unwrap();
assert_eq!(squeezed_axis0.shape(), vec![3, 1]);
let squeezed_axis2 = squeeze(&arr, Some(2)).unwrap();
assert_eq!(squeezed_axis2.shape(), vec![1, 3]);
}
#[test]
fn test_expand_dims_operations() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0]);
assert_eq!(arr.shape(), vec![3]);
let expanded0 = expand_dims(&arr, 0).unwrap();
assert_eq!(expanded0.shape(), vec![1, 3]);
let expanded1 = expand_dims(&arr, 1).unwrap();
assert_eq!(expanded1.shape(), vec![3, 1]);
let arr2d = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]).reshape(&[2, 2]);
let expanded2d = expand_dims(&arr2d, 1).unwrap();
assert_eq!(expanded2d.shape(), vec![2, 1, 2]);
}
#[test]
fn test_swapaxes_operations() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let arr = Array::from_vec(data).reshape(&[2, 3]);
let swapped = swapaxes(&arr, 0, 1).unwrap();
assert_eq!(swapped.shape(), vec![3, 2]);
let swapped_back = swapaxes(&swapped, 0, 1).unwrap();
assert_eq!(swapped_back.shape(), arr.shape());
}
#[test]
fn test_moveaxis_operations() {
let arr = Array::from_vec(vec![1.0; 24]).reshape(&[2, 3, 4]);
let moved = moveaxis(&arr, &[0], &[2]).unwrap();
assert_eq!(moved.shape(), vec![4, 2, 3]);
let moved2 = moveaxis(&arr, &[2], &[0]).unwrap();
assert_eq!(moved2.shape(), vec![3, 4, 2]);
assert_eq!(arr.shape(), vec![2, 3, 4]);
assert_eq!(moved.size(), arr.size()); }
}
#[cfg(test)]
mod arithmetic_operations_tests {
use super::*;
#[test]
fn test_basic_arithmetic() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]);
let b = Array::from_vec(vec![5.0, 6.0, 7.0, 8.0]);
let c = a.add(&b);
assert_eq!(c.to_vec(), vec![6.0, 8.0, 10.0, 12.0]);
let d = a.subtract(&b);
assert_eq!(d.to_vec(), vec![-4.0, -4.0, -4.0, -4.0]);
let e = a.multiply(&b);
assert_eq!(e.to_vec(), vec![5.0, 12.0, 21.0, 32.0]);
let f = a.divide(&b);
assert_relative_eq!(f.to_vec()[0], 0.2, epsilon = 1e-10);
assert_relative_eq!(f.to_vec()[1], 1.0 / 3.0, epsilon = 1e-10);
assert_relative_eq!(f.to_vec()[2], 3.0 / 7.0, epsilon = 1e-10);
assert_relative_eq!(f.to_vec()[3], 0.5, epsilon = 1e-10);
}
#[test]
fn test_scalar_operations() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]);
let b = a.add_scalar(5.0);
assert_eq!(b.to_vec(), vec![6.0, 7.0, 8.0, 9.0]);
let c = a.multiply_scalar(2.0);
assert_eq!(c.to_vec(), vec![2.0, 4.0, 6.0, 8.0]);
let d = a.subtract_scalar(1.0);
assert_eq!(d.to_vec(), vec![0.0, 1.0, 2.0, 3.0]);
let e = a.divide_scalar(2.0);
assert_eq!(e.to_vec(), vec![0.5, 1.0, 1.5, 2.0]);
}
#[test]
fn test_broadcasting_arithmetic() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]).reshape(&[2, 2]);
let b = Array::from_vec(vec![10.0, 20.0]);
let result = a.add_broadcast(&b.reshape(&[1, 2])).unwrap();
assert_eq!(result.shape(), vec![2, 2]);
let result_vec = result.to_vec();
assert_eq!(result_vec.len(), 4);
assert!(result_vec.iter().all(|&x| (11.0..=24.0).contains(&x)));
}
#[test]
fn test_in_place_style_operations() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]);
let b = Array::from_vec(vec![1.0, 1.0, 1.0, 1.0]);
let result = a.add(&b);
assert_eq!(result.to_vec(), vec![2.0, 3.0, 4.0, 5.0]);
let scaled = result.multiply_scalar(2.0);
assert_eq!(scaled.to_vec(), vec![4.0, 6.0, 8.0, 10.0]);
}
#[test]
fn test_arithmetic_with_different_types() {
let a = Array::from_vec(vec![10, 20, 30]);
let b = Array::from_vec(vec![1, 2, 3]);
let c = a.add(&b);
assert_eq!(c.to_vec(), vec![11, 22, 33]);
let d = a.subtract(&b);
assert_eq!(d.to_vec(), vec![9, 18, 27]);
let e = a.divide(&b);
assert_eq!(e.to_vec(), vec![10, 10, 10]);
}
#[test]
fn test_negative_operations() {
let a = Array::from_vec(vec![1.0, -2.0, 3.0, -4.0]);
let negated = a.map(|x| -x);
assert_eq!(negated.to_vec(), vec![-1.0, 2.0, -3.0, 4.0]);
}
}
#[cfg(test)]
mod indexing_operations_tests {
use super::*;
#[test]
fn test_basic_indexing() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
let arr = Array::from_vec(data).reshape(&[2, 3]);
assert_eq!(arr.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(arr.get(&[0, 1]).unwrap(), 2.0);
assert_eq!(arr.get(&[1, 0]).unwrap(), 4.0);
assert_eq!(arr.get(&[1, 2]).unwrap(), 6.0);
assert!(arr.get(&[2, 0]).is_err());
assert!(arr.get(&[0, 3]).is_err());
}
#[test]
fn test_set_operations() {
let mut arr = Array::<f64>::zeros(&[2, 3]);
arr.set(&[0, 0], 1.0).unwrap();
arr.set(&[0, 1], 2.0).unwrap();
arr.set(&[1, 2], 6.0).unwrap();
assert_eq!(arr.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(arr.get(&[0, 1]).unwrap(), 2.0);
assert_eq!(arr.get(&[1, 2]).unwrap(), 6.0);
assert_eq!(arr.get(&[1, 0]).unwrap(), 0.0);
assert!(arr.set(&[2, 0], 5.0).is_err());
}
#[test]
fn test_slice_operations() {
let data = vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
let arr = Array::from_vec(data).reshape(&[3, 3]);
let row0 = arr.slice(0, 0).unwrap();
assert_eq!(row0.shape(), vec![3]);
assert_eq!(row0.to_vec(), vec![1.0, 2.0, 3.0]);
let row1 = arr.slice(0, 1).unwrap();
assert_eq!(row1.to_vec(), vec![4.0, 5.0, 6.0]);
}
#[test]
fn test_boolean_indexing() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let mask = Array::from_vec(vec![true, false, true, false, true]);
let mut arr_copy = arr.clone();
arr_copy
.set_mask(&mask, &Array::from_vec(vec![10.0, 30.0, 50.0]))
.unwrap();
assert_eq!(arr_copy.to_vec(), vec![10.0, 2.0, 30.0, 4.0, 50.0]);
}
#[test]
fn test_advanced_indexing() {
let arr =
Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]).reshape(&[3, 3]);
let single_element = arr
.index(&[
numrs2::indexing::IndexSpec::Index(1),
numrs2::indexing::IndexSpec::Index(1),
])
.unwrap();
assert_eq!(single_element.to_vec(), vec![5.0]);
let row_slice = arr
.index(&[
numrs2::indexing::IndexSpec::Index(0),
numrs2::indexing::IndexSpec::All,
])
.unwrap();
assert_eq!(row_slice.shape(), vec![3]);
assert_eq!(row_slice.to_vec(), vec![1.0, 2.0, 3.0]);
let col_slice = arr
.index(&[
numrs2::indexing::IndexSpec::All,
numrs2::indexing::IndexSpec::Index(0),
])
.unwrap();
assert_eq!(col_slice.shape(), vec![3]);
assert_eq!(col_slice.to_vec(), vec![1.0, 4.0, 7.0]);
}
#[test]
fn test_multidimensional_indexing() {
let arr = Array::<f64>::from_vec((0..24).map(|x| x as f64).collect()).reshape(&[2, 3, 4]);
assert_eq!(arr.get(&[0, 0, 0]).unwrap(), 0.0);
assert_eq!(arr.get(&[0, 1, 2]).unwrap(), 6.0);
assert_eq!(arr.get(&[1, 2, 3]).unwrap(), 23.0);
assert!(arr.get(&[2, 0, 0]).is_err());
assert!(arr.get(&[0, 3, 0]).is_err());
assert!(arr.get(&[0, 0, 4]).is_err());
}
}
#[cfg(test)]
mod concatenation_stacking_tests {
use super::*;
#[test]
fn test_concatenate_1d() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![4.0, 5.0]);
let c = Array::from_vec(vec![6.0, 7.0, 8.0, 9.0]);
let result = concatenate(&[&a, &b, &c], 0).unwrap();
assert_eq!(result.shape(), vec![9]);
assert_eq!(
result.to_vec(),
vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
);
}
#[test]
fn test_concatenate_2d_axis0() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]).reshape(&[2, 2]);
let b = Array::from_vec(vec![5.0, 6.0, 7.0, 8.0]).reshape(&[2, 2]);
let result = concatenate(&[&a, &b], 0).unwrap();
assert_eq!(result.shape(), vec![4, 2]);
assert_eq!(result.size(), 8);
let result_vec = result.to_vec();
for i in 1..=8 {
assert!(result_vec.contains(&(i as f64)));
}
}
#[test]
fn test_concatenate_2d_axis1() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]).reshape(&[2, 2]);
let b = Array::from_vec(vec![5.0, 6.0, 7.0, 8.0]).reshape(&[2, 2]);
let result = concatenate(&[&a, &b], 1).unwrap();
assert_eq!(result.shape(), vec![2, 4]);
assert_eq!(result.size(), 8);
let result_vec = result.to_vec();
for i in 1..=8 {
assert!(result_vec.contains(&(i as f64)));
}
}
#[test]
fn test_stack_operations() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![4.0, 5.0, 6.0]);
let stacked0 = stack(&[&a, &b], 0).unwrap();
assert_eq!(stacked0.shape(), vec![2, 3]);
assert_eq!(stacked0.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(stacked0.get(&[0, 1]).unwrap(), 2.0);
assert_eq!(stacked0.get(&[1, 0]).unwrap(), 4.0);
assert_eq!(stacked0.get(&[1, 2]).unwrap(), 6.0);
let stacked1 = stack(&[&a, &b], 1).unwrap();
assert_eq!(stacked1.shape(), vec![3, 2]);
assert_eq!(stacked1.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(stacked1.get(&[0, 1]).unwrap(), 4.0);
assert_eq!(stacked1.get(&[1, 0]).unwrap(), 2.0);
assert_eq!(stacked1.get(&[2, 1]).unwrap(), 6.0);
}
#[test]
fn test_split_operations() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let splits = split(&arr, &[2, 4], 0).unwrap();
assert_eq!(splits.len(), 3);
assert_eq!(splits[0].to_vec(), vec![1.0, 2.0]);
assert_eq!(splits[1].to_vec(), vec![3.0, 4.0]);
assert_eq!(splits[2].to_vec(), vec![5.0, 6.0]);
let arr2d = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape(&[2, 3]);
let splits2d = split(&arr2d, &[1], 0).unwrap();
assert_eq!(splits2d.len(), 2);
assert_eq!(splits2d[0].shape(), vec![1, 3]);
assert_eq!(splits2d[1].shape(), vec![1, 3]);
}
#[test]
fn test_hsplit_vsplit() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape(&[2, 3]);
let h_splits = hsplit(&arr, 3).unwrap();
assert_eq!(h_splits.len(), 3);
for split in &h_splits {
assert_eq!(split.shape(), vec![2, 1]);
}
let v_splits = vsplit(&arr, 2).unwrap();
assert_eq!(v_splits.len(), 2);
for split in &v_splits {
assert_eq!(split.shape(), vec![1, 3]);
}
}
#[test]
fn test_r_and_c_operations() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![4.0, 5.0, 6.0]);
let r_result = r_(&[&a, &b]).unwrap();
assert_eq!(r_result.shape(), vec![6]);
assert_eq!(r_result.to_vec(), vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let c_result = c_(&[&a, &b]).unwrap();
assert_eq!(c_result.shape(), vec![3, 2]);
assert_eq!(c_result.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(c_result.get(&[0, 1]).unwrap(), 4.0);
assert_eq!(c_result.get(&[1, 0]).unwrap(), 2.0);
assert_eq!(c_result.get(&[2, 1]).unwrap(), 6.0);
}
}
#[cfg(test)]
mod comparison_tests {
use super::*;
#[test]
fn test_element_wise_comparisons() {
let a = Array::from_vec(vec![1, 3, 5, 7]);
let b = Array::from_vec(vec![2, 3, 4, 8]);
let gt_result = greater(&a, &b).unwrap();
assert_eq!(gt_result.to_vec(), vec![false, false, true, false]);
let ge_result = greater_equal(&a, &b).unwrap();
assert_eq!(ge_result.to_vec(), vec![false, true, true, false]);
let lt_result = less(&a, &b).unwrap();
assert_eq!(lt_result.to_vec(), vec![true, false, false, true]);
let le_result = less_equal(&a, &b).unwrap();
assert_eq!(le_result.to_vec(), vec![true, true, false, true]);
let eq_result = equal(&a, &b).unwrap();
assert_eq!(eq_result.to_vec(), vec![false, true, false, false]);
let ne_result = not_equal(&a, &b).unwrap();
assert_eq!(ne_result.to_vec(), vec![true, false, true, true]);
}
#[test]
fn test_array_equality() {
let a = Array::from_vec(vec![1, 2, 3, 4]);
let b = Array::from_vec(vec![1, 2, 3, 4]);
let c = Array::from_vec(vec![1, 2, 3, 5]);
assert!(array_equal(&a, &b, None));
assert!(!array_equal(&a, &c, None));
let d = Array::from_vec(vec![1, 2, 3, 4]).reshape(&[2, 2]);
assert!(!array_equal(&a, &d, None));
}
#[test]
fn test_allclose() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![1.0000001, 2.0000002, 3.0000003]);
let c = Array::from_vec(vec![1.01, 2.02, 3.03]);
assert!(allclose(&a, &b));
assert!(!allclose(&a, &c));
assert!(allclose_with_tol(&a, &c, 1e-2, 0.0));
}
#[test]
fn test_isclose_array() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![1.0000001, 2.0000002, 3.0000003]);
let close_result = isclose_array(&a, &b, 1e-7, 0.0).unwrap();
assert_eq!(close_result.to_vec(), vec![true, true, true]);
let strict_result = isclose_array(&a, &b, 1e-10, 0.0).unwrap();
assert_eq!(strict_result.to_vec(), vec![false, false, false]);
}
#[test]
fn test_all_any() {
let all_true = Array::from_vec(vec![true, true, true]);
let mixed = Array::from_vec(vec![true, false, true]);
let all_false = Array::from_vec(vec![false, false, false]);
assert!(all(&all_true));
assert!(!all(&mixed));
assert!(!all(&all_false));
assert!(any(&all_true));
assert!(any(&mixed));
assert!(!any(&all_false));
}
}
#[cfg(test)]
mod mathematical_operations_tests {
use super::*;
#[test]
fn test_basic_math_functions() {
let a = Array::from_vec(vec![1.0, 4.0, 9.0, 16.0]);
let sqrt_result = sqrt(&a);
for (i, &val) in sqrt_result.to_vec().iter().enumerate() {
assert_relative_eq!(val, (i + 1) as f64, epsilon = 1e-10);
}
let exp_result = exp(&a);
for (i, &val) in exp_result.to_vec().iter().enumerate() {
let expected = ((i + 1) * (i + 1)) as f64;
assert_relative_eq!(val, expected.exp(), epsilon = 1e-10);
}
let log_result = log(&a);
for (i, &val) in log_result.to_vec().iter().enumerate() {
let expected = ((i + 1) * (i + 1)) as f64;
assert_relative_eq!(val, expected.ln(), epsilon = 1e-10);
}
}
#[test]
fn test_trigonometric_functions() {
let angles = Array::from_vec(vec![
0.0,
std::f64::consts::PI / 6.0,
std::f64::consts::PI / 4.0,
std::f64::consts::PI / 3.0,
]);
let sin_result = sin(&angles);
assert_relative_eq!(sin_result.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(sin_result.to_vec()[1], 0.5, epsilon = 1e-10);
assert_relative_eq!(
sin_result.to_vec()[2],
1.0 / std::f64::consts::SQRT_2,
epsilon = 1e-10
);
let cos_result = cos(&angles);
assert_relative_eq!(cos_result.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(
cos_result.to_vec()[1],
(3.0_f64).sqrt() / 2.0,
epsilon = 1e-10
);
assert_relative_eq!(
cos_result.to_vec()[2],
1.0 / std::f64::consts::SQRT_2,
epsilon = 1e-10
);
let tan_result = tan(&angles);
assert_relative_eq!(tan_result.to_vec()[0], 0.0, epsilon = 1e-10);
}
#[test]
fn test_power_operations() {
let a = Array::from_vec(vec![2.0, 3.0, 4.0]);
let squared = a.pow(2.0);
assert_eq!(squared.to_vec(), vec![4.0, 9.0, 16.0]);
let b = Array::from_vec(vec![1.0, 2.0, 3.0]);
let pow_result = power(&a, &b).unwrap();
assert_relative_eq!(pow_result.to_vec()[0], 2.0, epsilon = 1e-10);
assert_relative_eq!(pow_result.to_vec()[1], 9.0, epsilon = 1e-10);
assert_relative_eq!(pow_result.to_vec()[2], 64.0, epsilon = 1e-10);
}
#[test]
fn test_absolute_operations() {
let a = Array::from_vec(vec![-1.0, 2.0, -3.0, 4.0]);
let abs_result = a.abs();
assert_eq!(abs_result.to_vec(), vec![1.0, 2.0, 3.0, 4.0]);
}
#[test]
fn test_rounding_operations() {
let a = Array::from_vec(vec![1.2, 2.7, -1.5, -2.3]);
let floor_result = floor(&a);
assert_eq!(floor_result.to_vec(), vec![1.0, 2.0, -2.0, -3.0]);
let ceil_result = ceil(&a);
assert_eq!(ceil_result.to_vec(), vec![2.0, 3.0, -1.0, -2.0]);
let round_result = round(&a);
assert_eq!(round_result.to_vec(), vec![1.0, 3.0, -2.0, -2.0]);
}
}
#[cfg(test)]
mod statistical_operations_tests {
use super::*;
#[test]
fn test_basic_statistics() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
assert_relative_eq!(a.mean(), 3.0, epsilon = 1e-10);
assert_relative_eq!(a.sum(), 15.0, epsilon = 1e-10);
assert_relative_eq!(a.min(), 1.0, epsilon = 1e-10);
assert_relative_eq!(a.max(), 5.0, epsilon = 1e-10);
assert_relative_eq!(a.var(), 2.0, epsilon = 1e-10);
assert_relative_eq!(a.std(), std::f64::consts::SQRT_2, epsilon = 1e-10);
}
#[test]
fn test_axis_statistics() {
let arr = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape(&[2, 3]);
let sum_axis0 = arr.sum_axis(0).unwrap();
assert_eq!(sum_axis0.shape(), vec![3]);
assert_eq!(sum_axis0.to_vec(), vec![5.0, 7.0, 9.0]);
let sum_axis1 = arr.sum_axis(1).unwrap();
assert_eq!(sum_axis1.shape(), vec![2]);
assert_eq!(sum_axis1.to_vec(), vec![6.0, 15.0]);
let mean_axis0 = arr.mean_axis(Some(0)).unwrap();
assert_eq!(mean_axis0.to_vec(), vec![2.5, 3.5, 4.5]);
let mean_axis1 = arr.mean_axis(Some(1)).unwrap();
assert_eq!(mean_axis1.to_vec(), vec![2.0, 5.0]);
}
#[test]
fn test_percentiles() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
assert_relative_eq!(a.percentile(0.0), 1.0, epsilon = 1e-10);
assert_relative_eq!(a.percentile(0.25), 2.0, epsilon = 1e-10);
assert_relative_eq!(a.percentile(0.5), 3.0, epsilon = 1e-10);
assert_relative_eq!(a.percentile(0.75), 4.0, epsilon = 1e-10);
assert_relative_eq!(a.percentile(1.0), 5.0, epsilon = 1e-10);
}
#[test]
fn test_correlation_covariance() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let b = Array::from_vec(vec![2.0, 4.0, 6.0, 8.0, 10.0]);
let cov_result = cov(&a, Some(&b), None, None, None).unwrap();
assert_eq!(cov_result.shape(), vec![2, 2]);
assert!(cov_result.get(&[0, 1]).unwrap() > 0.0);
let corr_result = corrcoef(&a, Some(&b), None).unwrap();
assert_eq!(corr_result.shape(), vec![2, 2]);
let corr_val: f64 = corr_result.get(&[0, 1]).unwrap();
assert!((corr_val - 1.0).abs() < 1e-10);
let c = Array::from_vec(vec![5.0, 4.0, 3.0, 2.0, 1.0]);
let corr_neg = corrcoef(&a, Some(&c), None).unwrap();
assert_eq!(corr_neg.shape(), vec![2, 2]);
let corr_neg_val: f64 = corr_neg.get(&[0, 1]).unwrap();
assert!((corr_neg_val - (-1.0)).abs() < 1e-10);
}
#[test]
fn test_histogram() {
let data = Array::from_vec(vec![1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0]);
let (counts, bins) = histogram(&data, 4, None, None).unwrap();
assert_eq!(counts.size(), 4);
assert_eq!(bins.size(), 5);
let total_count: f64 = counts.to_vec().iter().sum();
assert_eq!(total_count, 9.0);
assert_relative_eq!(bins.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(bins.to_vec()[4], 5.0, epsilon = 1e-10);
}
#[test]
fn test_cumulative_operations() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0]);
let cumsum_result = a.cumsum_axis(0).unwrap();
assert_eq!(cumsum_result.to_vec(), vec![1.0, 3.0, 6.0, 10.0]);
let expected_cumprod = vec![1.0, 2.0, 6.0, 24.0];
let a_vec = a.to_vec();
let mut manual_cumprod = Vec::new();
let mut product = 1.0;
for &val in &a_vec {
product *= val;
manual_cumprod.push(product);
}
assert_eq!(manual_cumprod, expected_cumprod);
}
}
#[cfg(test)]
mod sorting_searching_tests {
use super::*;
#[test]
fn test_array_ordering() {
let unsorted = Array::from_vec(vec![3, 1, 4, 1, 5, 9, 2, 6]);
let data_vec = unsorted.to_vec();
let min_val = *data_vec.iter().min().unwrap();
let max_val = *data_vec.iter().max().unwrap();
assert_eq!(min_val, 1);
assert_eq!(max_val, 9);
assert_eq!(data_vec.len(), 8);
assert!(data_vec.contains(&3));
assert!(data_vec.contains(&1));
assert!(data_vec.contains(&9));
}
#[test]
fn test_unique_operations() {
let arr = Array::from_vec(vec![1, 3, 2, 3, 1, 4, 2]);
let unique_result = unique(&arr, None, Some(true), None, None).unwrap();
let unique_values = unique_result.values.to_vec();
assert!(unique_values.contains(&1));
assert!(unique_values.contains(&2));
assert!(unique_values.contains(&3));
assert!(unique_values.contains(&4));
assert_eq!(unique_values.len(), 4);
if let Some(counts) = unique_result.counts {
let count_vec = counts.to_vec();
assert_eq!(count_vec.len(), 4);
assert!(count_vec.iter().all(|&c| (1..=2).contains(&c)));
} else {
println!("Counts not returned, which is acceptable for this implementation");
}
let basic_unique = unique(&arr, None, None, None, None).unwrap();
assert_eq!(basic_unique.values.size(), 4); }
#[test]
fn test_searchsorted() {
let sorted_arr = Array::from_vec(vec![1.0, 3.0, 5.0, 7.0, 9.0]);
let values = Array::from_vec(vec![0.0, 2.0, 4.0, 6.0, 8.0, 10.0]);
let indices = searchsorted(&sorted_arr, &values, "left").unwrap();
assert_eq!(indices.size(), 6);
let idx_vec = indices.to_vec();
assert_eq!(idx_vec[0], 0);
assert_eq!(idx_vec[1], 1);
assert_eq!(idx_vec[5], 5);
}
#[test]
fn test_min_max_operations() {
let arr = Array::from_vec(vec![3.0, 1.0, 4.0, 1.0, 5.0]);
let min_val = arr.min();
let max_val = arr.max();
assert_eq!(min_val, 1.0);
assert_eq!(max_val, 5.0);
let arr2d = Array::from_vec(vec![3, 1, 4, 2, 6, 5]).reshape(&[2, 3]);
let data_vec = arr2d.to_vec();
assert_eq!(data_vec.len(), 6);
assert!(data_vec.contains(&1));
assert!(data_vec.contains(&6));
}
}
#[cfg(test)]
mod repeat_tile_tests {
use super::*;
#[test]
fn test_repeat_operations() {
let arr = Array::from_vec(vec![1, 2, 3]);
let repeated = repeat(&arr, 2, None).unwrap();
assert_eq!(repeated.to_vec(), vec![1, 1, 2, 2, 3, 3]);
let arr2d = Array::from_vec(vec![1, 2, 3, 4]).reshape(&[2, 2]);
let repeated_axis0 = repeat(&arr2d, 2, Some(0)).unwrap();
assert_eq!(repeated_axis0.shape(), vec![4, 2]);
assert_eq!(repeated_axis0.to_vec(), vec![1, 2, 1, 2, 3, 4, 3, 4]);
}
#[test]
fn test_tile_operations() {
let arr = Array::from_vec(vec![1, 2, 3]);
let tiled = tile(&arr, &[2]).unwrap();
assert_eq!(tiled.to_vec(), vec![1, 2, 3, 1, 2, 3]);
let arr2d = Array::from_vec(vec![1, 2, 3, 4]).reshape(&[2, 2]);
let tiled2d = tile(&arr2d, &[2, 1]).unwrap();
assert_eq!(tiled2d.shape(), vec![4, 2]);
assert_eq!(tiled2d.to_vec(), vec![1, 2, 3, 4, 1, 2, 3, 4]);
}
#[test]
fn test_tile_multidimensional() {
let arr = Array::from_vec(vec![1, 2]);
let tiled = tile(&arr, &[3, 2]).unwrap();
assert_eq!(tiled.shape(), vec![3, 6]); assert_eq!(tiled.size(), 18);
let tiled_vec = tiled.to_vec();
assert_eq!(tiled_vec.len(), 18);
let count_1 = tiled_vec.iter().filter(|&&x| x == 1).count();
let count_2 = tiled_vec.iter().filter(|&&x| x == 2).count();
assert_eq!(count_1 + count_2, 18); assert!(count_1 > 0 && count_2 > 0); }
}
#[test]
fn test_comprehensive_operations_integration() {
let data1 = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0]).reshape(&[2, 3]);
let data2 = Array::from_vec(vec![6.0, 5.0, 4.0, 3.0, 2.0, 1.0]).reshape(&[2, 3]);
let sum_result = data1.add(&data2);
assert_eq!(sum_result.shape(), vec![2, 3]);
assert!(sum_result.to_vec().iter().all(|&x| x == 7.0));
let mean_val = sum_result.mean();
assert_relative_eq!(mean_val, 7.0, epsilon = 1e-10);
let flattened = sum_result.flatten(None);
assert_eq!(flattened.shape(), vec![6]);
let comparison = greater(&data1, &data2).unwrap();
assert_eq!(comparison.shape(), vec![2, 3]);
let simd_result = simd_add(&data1, &data2).unwrap();
assert_eq!(simd_result.shape(), vec![2, 3]);
assert_eq!(simd_result.to_vec(), sum_result.to_vec());
let concatenated = concatenate(&[&data1, &data2], 0).unwrap();
assert_eq!(concatenated.shape(), vec![4, 3]);
assert_eq!(concatenated.size(), 12);
assert_eq!(concatenated.get(&[0, 0]).unwrap(), 1.0);
assert_eq!(concatenated.get(&[2, 0]).unwrap(), 6.0);
println!("All comprehensive integration tests passed!");
}