parry2d/utils/
sort.rs

1#[cfg(feature = "dim3")]
2#[inline]
3/// Sorts a set of two values in increasing order.
4///
5/// This is a simple utility function that takes two values and returns them
6/// as a tuple in sorted order (smallest first). This function is only available
7/// in 3D mode (`dim3` feature).
8///
9/// # Arguments
10///
11/// * `a` - The first value
12/// * `b` - The second value
13///
14/// # Returns
15///
16/// A tuple `(min, max)` where `min` is the smaller value and `max` is the larger value.
17///
18/// # Examples
19///
20/// ```
21/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
22/// use parry3d::utils::sort2;
23///
24/// let (min, max) = sort2(5.0, 2.0);
25/// assert_eq!(min, 2.0);
26/// assert_eq!(max, 5.0);
27///
28/// // Already sorted values remain in the same order
29/// let (min, max) = sort2(1.0, 3.0);
30/// assert_eq!(min, 1.0);
31/// assert_eq!(max, 3.0);
32/// # }
33/// ```
34pub fn sort2<T: PartialOrd + Copy>(a: T, b: T) -> (T, T) {
35    if a > b {
36        (b, a)
37    } else {
38        (a, b)
39    }
40}
41
42/// Sorts a set of three values in increasing order.
43///
44/// This function efficiently sorts three values using a minimal number of comparisons
45/// (between 2 and 3 comparisons). The values are passed by reference and references
46/// are returned, making this efficient for larger types.
47///
48/// # Arguments
49///
50/// * `a` - Reference to the first value
51/// * `b` - Reference to the second value
52/// * `c` - Reference to the third value
53///
54/// # Returns
55///
56/// A tuple of three references `(&min, &mid, &max)` in sorted order.
57///
58/// # Examples
59///
60/// ## Basic Sorting
61///
62/// ```
63/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
64/// use parry3d::utils::sort3;
65///
66/// let x = 5.0;
67/// let y = 2.0;
68/// let z = 8.0;
69///
70/// let (min, mid, max) = sort3(&x, &y, &z);
71///
72/// assert_eq!(*min, 2.0);
73/// assert_eq!(*mid, 5.0);
74/// assert_eq!(*max, 8.0);
75/// # }
76/// ```
77///
78/// ## All Permutations Work
79///
80/// ```
81/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
82/// use parry3d::utils::sort3;
83///
84/// let a = 1.0;
85/// let b = 2.0;
86/// let c = 3.0;
87///
88/// // All orderings produce the same sorted result
89/// let (min1, mid1, max1) = sort3(&a, &b, &c);
90/// let (min2, mid2, max2) = sort3(&c, &a, &b);
91/// let (min3, mid3, max3) = sort3(&b, &c, &a);
92///
93/// assert_eq!(*min1, *min2);
94/// assert_eq!(*min1, *min3);
95/// assert_eq!(*max1, *max2);
96/// assert_eq!(*max1, *max3);
97/// # }
98/// ```
99///
100/// ## Finding Median of Three
101///
102/// ```
103/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
104/// use parry3d::utils::sort3;
105///
106/// let values = [10.0, 5.0, 7.0];
107/// let (_, median, _) = sort3(&values[0], &values[1], &values[2]);
108///
109/// // The middle value is the median
110/// assert_eq!(*median, 7.0);
111/// # }
112/// ```
113///
114/// ## Works with Integers
115///
116/// ```
117/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
118/// use parry3d::utils::sort3;
119///
120/// let x = 42;
121/// let y = 17;
122/// let z = 99;
123///
124/// let (min, mid, max) = sort3(&x, &y, &z);
125///
126/// assert_eq!(*min, 17);
127/// assert_eq!(*mid, 42);
128/// assert_eq!(*max, 99);
129/// # }
130/// ```
131#[inline]
132pub fn sort3<'a, T: PartialOrd + Copy>(a: &'a T, b: &'a T, c: &'a T) -> (&'a T, &'a T, &'a T) {
133    let a_b = *a > *b;
134    let a_c = *a > *c;
135    let b_c = *b > *c;
136
137    let sa;
138    let sb;
139    let sc;
140
141    // Sort the three values.
142    if a_b {
143        // a > b
144        if a_c {
145            // a > c
146            sc = a;
147
148            if b_c {
149                // b > c
150                sa = c;
151                sb = b;
152            } else {
153                // b <= c
154                sa = b;
155                sb = c;
156            }
157        } else {
158            // a <= c
159            sa = b;
160            sb = a;
161            sc = c;
162        }
163    } else {
164        // a < b
165        if !a_c {
166            // a <= c
167            sa = a;
168
169            if b_c {
170                // b > c
171                sb = c;
172                sc = b;
173            } else {
174                sb = b;
175                sc = c;
176            }
177        } else {
178            // a > c
179            sa = c;
180            sb = a;
181            sc = b;
182        }
183    }
184
185    (sa, sb, sc)
186}