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}