common_function/scalars/vector/distance/
cos.rs1use nalgebra::DVectorView;
16
17pub fn cos(lhs: &[f32], rhs: &[f32]) -> f32 {
21 let lhs_vec = DVectorView::from_slice(lhs, lhs.len());
22 let rhs_vec = DVectorView::from_slice(rhs, rhs.len());
23
24 let dot_product = lhs_vec.dot(&rhs_vec);
25 let lhs_norm = lhs_vec.norm();
26 let rhs_norm = rhs_vec.norm();
27 if dot_product.abs() < f32::EPSILON
28 || lhs_norm.abs() < f32::EPSILON
29 || rhs_norm.abs() < f32::EPSILON
30 {
31 return 1.0;
32 }
33
34 let cos_similar = dot_product / (lhs_norm * rhs_norm);
35 let res = 1.0 - cos_similar;
36 if res.abs() < f32::EPSILON { 0.0 } else { res }
37}
38
39#[cfg(test)]
40mod tests {
41 use approx::assert_relative_eq;
42
43 use super::*;
44
45 #[test]
46 fn test_cos_scalar() {
47 let lhs = vec![1.0, 2.0, 3.0];
48 let rhs = vec![1.0, 2.0, 3.0];
49 assert_relative_eq!(cos(&lhs, &rhs), 0.0, epsilon = 1e-2);
50
51 let lhs = vec![1.0, 2.0, 3.0];
52 let rhs = vec![4.0, 5.0, 6.0];
53 assert_relative_eq!(cos(&lhs, &rhs), 0.025, epsilon = 1e-2);
54
55 let lhs = vec![1.0, 2.0, 3.0];
56 let rhs = vec![7.0, 8.0, 9.0];
57 assert_relative_eq!(cos(&lhs, &rhs), 0.04, epsilon = 1e-2);
58
59 let lhs = vec![0.0, 0.0, 0.0];
60 let rhs = vec![1.0, 2.0, 3.0];
61 assert_relative_eq!(cos(&lhs, &rhs), 1.0, epsilon = 1e-2);
62
63 let lhs = vec![0.0, 0.0, 0.0];
64 let rhs = vec![4.0, 5.0, 6.0];
65 assert_relative_eq!(cos(&lhs, &rhs), 1.0, epsilon = 1e-2);
66
67 let lhs = vec![0.0, 0.0, 0.0];
68 let rhs = vec![7.0, 8.0, 9.0];
69 assert_relative_eq!(cos(&lhs, &rhs), 1.0, epsilon = 1e-2);
70
71 let lhs = vec![7.0, 8.0, 9.0];
72 let rhs = vec![1.0, 2.0, 3.0];
73 assert_relative_eq!(cos(&lhs, &rhs), 0.04, epsilon = 1e-2);
74
75 let lhs = vec![7.0, 8.0, 9.0];
76 let rhs = vec![4.0, 5.0, 6.0];
77 assert_relative_eq!(cos(&lhs, &rhs), 0.0, epsilon = 1e-2);
78
79 let lhs = vec![7.0, 8.0, 9.0];
80 let rhs = vec![7.0, 8.0, 9.0];
81 assert_relative_eq!(cos(&lhs, &rhs), 0.0, epsilon = 1e-2);
82 }
83}