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