1 use crate::MediaTrackSettings;
2
select_optimal_candidates<'a, I>(candidates: I) -> Vec<&'a MediaTrackSettings> where I: IntoIterator<Item = (&'a MediaTrackSettings, f64)>,3 pub(super) fn select_optimal_candidates<'a, I>(candidates: I) -> Vec<&'a MediaTrackSettings>
4 where
5 I: IntoIterator<Item = (&'a MediaTrackSettings, f64)>,
6 {
7 let mut optimal_candidates = vec![];
8 let mut optimal_fitness_distance = f64::INFINITY;
9
10 for (candidate, fitness_distance) in candidates {
11 use std::cmp::Ordering;
12
13 #[cfg(feature = "total_cmp")]
14 let ordering = fitness_distance.total_cmp(&optimal_fitness_distance);
15
16 // TODO: remove fallback once MSRV has been bumped to 1.62 or later:
17 #[cfg(not(feature = "total_cmp"))]
18 let ordering = {
19 // See http://doc.rust-lang.org/1.65.0/core/primitive.f64.html#method.total_cmp:
20
21 let mut left = fitness_distance.to_bits() as i64;
22 let mut right = optimal_fitness_distance.to_bits() as i64;
23
24 left ^= (((left >> 63) as u64) >> 1) as i64;
25 right ^= (((right >> 63) as u64) >> 1) as i64;
26
27 left.cmp(&right)
28 };
29
30 if ordering == Ordering::Less {
31 // Candidate is new optimal, so drop current selection:
32 optimal_candidates.clear();
33 optimal_fitness_distance = fitness_distance;
34 }
35
36 if ordering != Ordering::Greater {
37 // Candidate is optimal, so add to selection:
38 optimal_candidates.push(candidate);
39 }
40 }
41
42 optimal_candidates
43 }
44
45 #[cfg(test)]
46 mod tests {
47 use crate::MediaTrackSettings;
48
49 use super::select_optimal_candidates;
50
51 #[test]
monotonic_increasing()52 fn monotonic_increasing() {
53 let settings = vec![
54 MediaTrackSettings::default(),
55 MediaTrackSettings::default(),
56 MediaTrackSettings::default(),
57 MediaTrackSettings::default(),
58 ];
59
60 let candidates = vec![
61 (&settings[0], 0.1),
62 (&settings[1], 0.1),
63 (&settings[2], 0.2),
64 (&settings[3], 0.3),
65 ];
66
67 let actual = select_optimal_candidates(candidates);
68
69 let expected = vec![&settings[0], &settings[1]];
70
71 assert_eq!(actual, expected);
72 }
73
74 #[test]
monotonic_decreasing()75 fn monotonic_decreasing() {
76 let settings = vec![
77 MediaTrackSettings::default(),
78 MediaTrackSettings::default(),
79 MediaTrackSettings::default(),
80 MediaTrackSettings::default(),
81 ];
82
83 let candidates = vec![
84 (&settings[0], 0.3),
85 (&settings[1], 0.2),
86 (&settings[2], 0.1),
87 (&settings[3], 0.1),
88 ];
89
90 let actual = select_optimal_candidates(candidates);
91
92 let expected = vec![&settings[2], &settings[3]];
93
94 assert_eq!(actual, expected);
95 }
96
97 #[test]
alternating()98 fn alternating() {
99 let settings = vec![
100 MediaTrackSettings::default(),
101 MediaTrackSettings::default(),
102 MediaTrackSettings::default(),
103 MediaTrackSettings::default(),
104 ];
105
106 let candidates = vec![
107 (&settings[0], 0.2),
108 (&settings[1], 0.1),
109 (&settings[2], 0.2),
110 (&settings[3], 0.1),
111 ];
112
113 let actual = select_optimal_candidates(candidates);
114
115 let expected = vec![&settings[1], &settings[3]];
116
117 assert_eq!(actual, expected);
118 }
119 }
120