fdars_core/streaming_depth/
mbd.rs1use crate::iter_maybe_parallel;
4use crate::matrix::FdMatrix;
5#[cfg(feature = "parallel")]
6use rayon::iter::ParallelIterator;
7
8use super::sorted_ref::SortedReferenceState;
9use super::{c2, StreamingDepth};
10
11#[derive(Debug, Clone, PartialEq)]
22pub struct StreamingMbd {
23 state: SortedReferenceState,
24}
25
26impl StreamingMbd {
27 pub fn new(state: SortedReferenceState) -> Self {
28 Self { state }
29 }
30
31 #[inline]
33 fn mbd_one_inner(&self, curve: &[f64]) -> f64 {
34 let n = self.state.nori;
35 if n < 2 {
36 return 0.0;
37 }
38 let cn2 = c2(n);
39 let t_len = self.state.n_points;
40 let mut total = 0usize;
41 for t in 0..t_len {
42 let (below, above) = self.state.rank_at(t, curve[t]);
43 total += cn2 - c2(below) - c2(above);
44 }
45 total as f64 / (cn2 as f64 * t_len as f64)
46 }
47
48 #[inline]
50 fn mbd_one_from_row(&self, data: &FdMatrix, row: usize) -> f64 {
51 let n = self.state.nori;
52 if n < 2 {
53 return 0.0;
54 }
55 let cn2 = c2(n);
56 let t_len = self.state.n_points;
57 let mut total = 0usize;
58 for t in 0..t_len {
59 let (below, above) = self.state.rank_at(t, data[(row, t)]);
60 total += cn2 - c2(below) - c2(above);
61 }
62 total as f64 / (cn2 as f64 * t_len as f64)
63 }
64}
65
66impl StreamingDepth for StreamingMbd {
67 fn depth_one(&self, curve: &[f64]) -> f64 {
68 self.mbd_one_inner(curve)
69 }
70
71 fn depth_batch(&self, data_obj: &FdMatrix) -> Vec<f64> {
72 let nobj = data_obj.nrows();
73 if nobj == 0 || self.state.n_points == 0 || self.state.nori < 2 {
74 return vec![0.0; nobj];
75 }
76 iter_maybe_parallel!(0..nobj)
77 .map(|i| self.mbd_one_from_row(data_obj, i))
78 .collect()
79 }
80
81 fn n_points(&self) -> usize {
82 self.state.n_points
83 }
84
85 fn n_reference(&self) -> usize {
86 self.state.nori
87 }
88}