sklears_utils/array_utils/
inplace.rs

1//! In-place array operations for memory efficiency
2
3use crate::{UtilsError, UtilsResult};
4use scirs2_core::ndarray::Array1;
5use scirs2_core::numeric::{Float, ToPrimitive};
6
7/// Standardize array in-place
8pub fn array_standardize_inplace<T>(array: &mut Array1<T>) -> UtilsResult<()>
9where
10    T: Float + Clone + ToPrimitive,
11{
12    if array.len() <= 1 {
13        return Err(UtilsError::InsufficientData {
14            min: 2,
15            actual: array.len(),
16        });
17    }
18
19    // Calculate mean
20    let sum = array.iter().fold(T::zero(), |acc, &x| acc + x);
21    let mean = sum / T::from(array.len()).unwrap();
22
23    // Calculate standard deviation
24    let variance = array
25        .iter()
26        .map(|&x| {
27            let diff = x - mean;
28            diff * diff
29        })
30        .fold(T::zero(), |acc, x| acc + x)
31        / T::from(array.len() - 1).unwrap();
32
33    let std = variance.sqrt();
34
35    if std.abs() < T::from(1e-10).unwrap() {
36        return Err(UtilsError::InvalidParameter(
37            "Standard deviation too small for standardization".to_string(),
38        ));
39    }
40
41    // Apply standardization in-place
42    for x in array.iter_mut() {
43        *x = (*x - mean) / std;
44    }
45
46    Ok(())
47}
48
49/// Min-max normalize array in-place to [0, 1] range
50pub fn array_min_max_normalize_inplace<T>(array: &mut Array1<T>) -> UtilsResult<()>
51where
52    T: PartialOrd + Float + Clone,
53{
54    if array.is_empty() {
55        return Err(UtilsError::EmptyInput);
56    }
57
58    let mut min_val = array[0];
59    let mut max_val = array[0];
60
61    // Find min and max
62    for &value in array.iter() {
63        if value < min_val {
64            min_val = value;
65        }
66        if value > max_val {
67            max_val = value;
68        }
69    }
70
71    let range = max_val - min_val;
72
73    if range.abs() < T::from(1e-10).unwrap() {
74        // All values are the same, set to zero
75        for x in array.iter_mut() {
76            *x = T::zero();
77        }
78    } else {
79        // Apply normalization in-place
80        for x in array.iter_mut() {
81            *x = (*x - min_val) / range;
82        }
83    }
84
85    Ok(())
86}
87
88/// Apply function to array elements in-place
89pub fn array_apply_inplace<T, F>(array: &mut Array1<T>, func: F) -> UtilsResult<()>
90where
91    T: Clone,
92    F: Fn(T) -> T,
93{
94    for x in array.iter_mut() {
95        *x = func(x.clone());
96    }
97    Ok(())
98}
99
100/// Scale array by constant in-place
101pub fn array_scale_inplace<T>(array: &mut Array1<T>, scalar: T) -> UtilsResult<()>
102where
103    T: Float + Clone,
104{
105    for x in array.iter_mut() {
106        *x = *x * scalar;
107    }
108    Ok(())
109}
110
111/// Add constant to all array elements in-place
112pub fn array_add_constant_inplace<T>(array: &mut Array1<T>, constant: T) -> UtilsResult<()>
113where
114    T: Float + Clone,
115{
116    for x in array.iter_mut() {
117        *x = *x + constant;
118    }
119    Ok(())
120}