parry2d_f64/utils/
median.rs

1use crate::math::Real;
2use na;
3
4/// Computes the median of a set of values.
5///
6/// The median is the middle value when the data is sorted. For an even number of values,
7/// it returns the average of the two middle values. This function modifies the input slice
8/// by sorting it in-place.
9///
10/// # Arguments
11///
12/// * `vals` - A mutable slice of values. Must contain at least one value. The slice will be
13///   sorted in-place as a side effect.
14///
15/// # Returns
16///
17/// The median value as a `Real`.
18///
19/// # Panics
20///
21/// Panics if the input slice is empty.
22///
23/// # Examples
24///
25/// ## Odd Number of Values
26///
27/// ```
28/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
29/// use parry2d::math::Real;
30/// use parry2d::utils::median;
31///
32/// let mut values = vec![5.0, 1.0, 3.0, 9.0, 2.0];
33/// let med = median(&mut values);
34///
35/// // With 5 values, the median is the 3rd value when sorted: [1, 2, 3, 5, 9]
36/// assert_eq!(med, 3.0);
37/// # }
38/// ```
39///
40/// ## Even Number of Values
41///
42/// ```
43/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
44/// use parry2d::math::Real;
45/// use parry2d::utils::median;
46///
47/// let mut values = vec![1.0, 2.0, 3.0, 4.0];
48/// let med = median(&mut values);
49///
50/// // With 4 values, median is average of middle two: (2 + 3) / 2 = 2.5
51/// assert_eq!(med, 2.5);
52/// # }
53/// ```
54///
55/// ## Single Value
56///
57/// ```
58/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
59/// use parry2d::math::Real;
60/// use parry2d::utils::median;
61///
62/// let mut values = vec![42.0];
63/// let med = median(&mut values);
64///
65/// // The median of a single value is the value itself
66/// assert_eq!(med, 42.0);
67/// # }
68/// ```
69///
70/// ## Values Are Sorted In-Place
71///
72/// ```
73/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
74/// use parry2d::utils::median;
75///
76/// let mut values = vec![5.0, 1.0, 3.0];
77/// let med = median(&mut values);
78///
79/// // After calling median, the values are sorted
80/// assert_eq!(values, vec![1.0, 3.0, 5.0]);
81/// assert_eq!(med, 3.0);
82/// # }
83/// ```
84#[inline]
85pub fn median(vals: &mut [Real]) -> Real {
86    assert!(
87        !vals.is_empty(),
88        "Cannot compute the median of zero values."
89    );
90
91    vals.sort_by(|a, b| a.partial_cmp(b).unwrap());
92
93    let n = vals.len();
94
95    if n.is_multiple_of(2) {
96        (vals[n / 2 - 1] + vals[n / 2]) / na::convert::<f64, Real>(2.0)
97    } else {
98        vals[n / 2]
99    }
100}