sklears_python/metrics/
common.rs1pub use numpy::PyReadonlyArray1;
8pub use pyo3::exceptions::PyValueError;
9pub use pyo3::prelude::*;
10pub use scirs2_core::ndarray::Array1;
11
12pub type MetricResult<T> = Result<T, PyValueError>;
14
15pub fn validate_arrays_same_length(y_true: &Array1<f64>, y_pred: &Array1<f64>) -> PyResult<()> {
17 if y_true.len() != y_pred.len() {
18 return Err(PyValueError::new_err(format!(
19 "y_true and y_pred must have the same length: {} vs {}",
20 y_true.len(),
21 y_pred.len()
22 )));
23 }
24
25 if y_true.is_empty() {
26 return Err(PyValueError::new_err("y_true and y_pred must not be empty"));
27 }
28
29 Ok(())
30}
31
32pub fn validate_int_arrays_same_length(y_true: &[i32], y_pred: &[i32]) -> PyResult<()> {
34 if y_true.len() != y_pred.len() {
35 return Err(PyValueError::new_err(format!(
36 "y_true and y_pred must have the same length: {} vs {}",
37 y_true.len(),
38 y_pred.len()
39 )));
40 }
41
42 if y_true.is_empty() {
43 return Err(PyValueError::new_err("y_true and y_pred must not be empty"));
44 }
45
46 Ok(())
47}
48
49pub fn validate_sample_weight(
51 sample_weight: &Option<Array1<f64>>,
52 n_samples: usize,
53) -> PyResult<()> {
54 if let Some(weights) = sample_weight {
55 if weights.len() != n_samples {
56 return Err(PyValueError::new_err(format!(
57 "sample_weight must have the same length as y_true: {} vs {}",
58 weights.len(),
59 n_samples
60 )));
61 }
62
63 if weights.iter().any(|&w| w < 0.0 || !w.is_finite()) {
64 return Err(PyValueError::new_err(
65 "sample_weight must contain non-negative finite values",
66 ));
67 }
68 }
69
70 Ok(())
71}
72
73pub fn apply_sample_weight(
75 values: &Array1<f64>,
76 sample_weight: &Option<Array1<f64>>,
77) -> Array1<f64> {
78 match sample_weight {
79 Some(weights) => values * weights,
80 None => values.clone(),
81 }
82}