use crate::{UtilsError, UtilsResult};
use scirs2_core::ndarray::Array1;
use scirs2_core::numeric::{Float, ToPrimitive};
pub fn array_standardize_inplace<T>(array: &mut Array1<T>) -> UtilsResult<()>
where
T: Float + Clone + ToPrimitive,
{
if array.len() <= 1 {
return Err(UtilsError::InsufficientData {
min: 2,
actual: array.len(),
});
}
let sum = array.iter().fold(T::zero(), |acc, &x| acc + x);
let mean = sum / T::from(array.len()).expect("operation should succeed");
let variance = array
.iter()
.map(|&x| {
let diff = x - mean;
diff * diff
})
.fold(T::zero(), |acc, x| acc + x)
/ T::from(array.len() - 1).expect("operation should succeed");
let std = variance.sqrt();
if std.abs() < T::from(1e-10).expect("operation should succeed") {
return Err(UtilsError::InvalidParameter(
"Standard deviation too small for standardization".to_string(),
));
}
for x in array.iter_mut() {
*x = (*x - mean) / std;
}
Ok(())
}
pub fn array_min_max_normalize_inplace<T>(array: &mut Array1<T>) -> UtilsResult<()>
where
T: PartialOrd + Float + Clone,
{
if array.is_empty() {
return Err(UtilsError::EmptyInput);
}
let mut min_val = array[0];
let mut max_val = array[0];
for &value in array.iter() {
if value < min_val {
min_val = value;
}
if value > max_val {
max_val = value;
}
}
let range = max_val - min_val;
if range.abs() < T::from(1e-10).expect("operation should succeed") {
for x in array.iter_mut() {
*x = T::zero();
}
} else {
for x in array.iter_mut() {
*x = (*x - min_val) / range;
}
}
Ok(())
}
pub fn array_apply_inplace<T, F>(array: &mut Array1<T>, func: F) -> UtilsResult<()>
where
T: Clone,
F: Fn(T) -> T,
{
for x in array.iter_mut() {
*x = func(x.clone());
}
Ok(())
}
pub fn array_scale_inplace<T>(array: &mut Array1<T>, scalar: T) -> UtilsResult<()>
where
T: Float + Clone,
{
for x in array.iter_mut() {
*x = *x * scalar;
}
Ok(())
}
pub fn array_add_constant_inplace<T>(array: &mut Array1<T>, constant: T) -> UtilsResult<()>
where
T: Float + Clone,
{
for x in array.iter_mut() {
*x = *x + constant;
}
Ok(())
}