nalgebra/base/min_max.rs
1use crate::storage::RawStorage;
2use crate::{ComplexField, Dim, Matrix, Scalar, SimdComplexField, SimdPartialOrd, Vector};
3use num::{Signed, Zero};
4use simba::simd::SimdSigned;
5
6/// # Find the min and max components
7impl<T: Scalar, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
8 /// Returns the absolute value of the component with the largest absolute value.
9 /// # Example
10 /// ```
11 /// # use nalgebra::Vector3;
12 /// assert_eq!(Vector3::new(-1.0, 2.0, 3.0).amax(), 3.0);
13 /// assert_eq!(Vector3::new(-1.0, -2.0, -3.0).amax(), 3.0);
14 /// ```
15 #[inline]
16 #[must_use]
17 pub fn amax(&self) -> T
18 where
19 T: Zero + SimdSigned + SimdPartialOrd,
20 {
21 self.fold_with(
22 |e| e.unwrap_or(&T::zero()).simd_abs(),
23 |a, b| a.simd_max(b.simd_abs()),
24 )
25 }
26
27 /// Returns the the 1-norm of the complex component with the largest 1-norm.
28 /// # Example
29 /// ```
30 /// # use nalgebra::{Vector3, Complex};
31 /// assert_eq!(Vector3::new(
32 /// Complex::new(-3.0, -2.0),
33 /// Complex::new(1.0, 2.0),
34 /// Complex::new(1.0, 3.0)).camax(), 5.0);
35 /// ```
36 #[inline]
37 #[must_use]
38 pub fn camax(&self) -> T::SimdRealField
39 where
40 T: SimdComplexField,
41 {
42 self.fold_with(
43 |e| e.unwrap_or(&T::zero()).clone().simd_norm1(),
44 |a, b| a.simd_max(b.clone().simd_norm1()),
45 )
46 }
47
48 /// Returns the component with the largest value.
49 /// # Example
50 /// ```
51 /// # use nalgebra::Vector3;
52 /// assert_eq!(Vector3::new(-1.0, 2.0, 3.0).max(), 3.0);
53 /// assert_eq!(Vector3::new(-1.0, -2.0, -3.0).max(), -1.0);
54 /// assert_eq!(Vector3::new(5u32, 2, 3).max(), 5);
55 /// ```
56 #[inline]
57 #[must_use]
58 pub fn max(&self) -> T
59 where
60 T: SimdPartialOrd + Zero,
61 {
62 self.fold_with(
63 |e| e.cloned().unwrap_or_else(T::zero),
64 |a, b| a.simd_max(b.clone()),
65 )
66 }
67
68 /// Returns the absolute value of the component with the smallest absolute value.
69 /// # Example
70 /// ```
71 /// # use nalgebra::Vector3;
72 /// assert_eq!(Vector3::new(-1.0, 2.0, -3.0).amin(), 1.0);
73 /// assert_eq!(Vector3::new(10.0, 2.0, 30.0).amin(), 2.0);
74 /// ```
75 #[inline]
76 #[must_use]
77 pub fn amin(&self) -> T
78 where
79 T: Zero + SimdPartialOrd + SimdSigned,
80 {
81 self.fold_with(
82 |e| e.map(|e| e.simd_abs()).unwrap_or_else(T::zero),
83 |a, b| a.simd_min(b.simd_abs()),
84 )
85 }
86
87 /// Returns the the 1-norm of the complex component with the smallest 1-norm.
88 /// # Example
89 /// ```
90 /// # use nalgebra::{Vector3, Complex};
91 /// assert_eq!(Vector3::new(
92 /// Complex::new(-3.0, -2.0),
93 /// Complex::new(1.0, 2.0),
94 /// Complex::new(1.0, 3.0)).camin(), 3.0);
95 /// ```
96 #[inline]
97 #[must_use]
98 pub fn camin(&self) -> T::SimdRealField
99 where
100 T: SimdComplexField,
101 {
102 self.fold_with(
103 |e| {
104 e.map(|e| e.clone().simd_norm1())
105 .unwrap_or_else(T::SimdRealField::zero)
106 },
107 |a, b| a.simd_min(b.clone().simd_norm1()),
108 )
109 }
110
111 /// Returns the component with the smallest value.
112 /// # Example
113 /// ```
114 /// # use nalgebra::Vector3;
115 /// assert_eq!(Vector3::new(-1.0, 2.0, 3.0).min(), -1.0);
116 /// assert_eq!(Vector3::new(1.0, 2.0, 3.0).min(), 1.0);
117 /// assert_eq!(Vector3::new(5u32, 2, 3).min(), 2);
118 /// ```
119 #[inline]
120 #[must_use]
121 pub fn min(&self) -> T
122 where
123 T: SimdPartialOrd + Zero,
124 {
125 self.fold_with(
126 |e| e.cloned().unwrap_or_else(T::zero),
127 |a, b| a.simd_min(b.clone()),
128 )
129 }
130
131 /// Computes the index of the matrix component with the largest absolute value.
132 ///
133 /// # Examples:
134 ///
135 /// ```
136 /// # extern crate num_complex;
137 /// # extern crate nalgebra;
138 /// # use num_complex::Complex;
139 /// # use nalgebra::Matrix2x3;
140 /// let mat = Matrix2x3::new(Complex::new(11.0, 1.0), Complex::new(-12.0, 2.0), Complex::new(13.0, 3.0),
141 /// Complex::new(21.0, 43.0), Complex::new(22.0, 5.0), Complex::new(-23.0, 0.0));
142 /// assert_eq!(mat.icamax_full(), (1, 0));
143 /// ```
144 #[inline]
145 #[must_use]
146 pub fn icamax_full(&self) -> (usize, usize)
147 where
148 T: ComplexField,
149 {
150 assert!(!self.is_empty(), "The input matrix must not be empty.");
151
152 let mut the_max = unsafe { self.get_unchecked((0, 0)).clone().norm1() };
153 let mut the_ij = (0, 0);
154
155 for j in 0..self.ncols() {
156 for i in 0..self.nrows() {
157 let val = unsafe { self.get_unchecked((i, j)).clone().norm1() };
158
159 if val > the_max {
160 the_max = val;
161 the_ij = (i, j);
162 }
163 }
164 }
165
166 the_ij
167 }
168}
169
170impl<T: Scalar + PartialOrd + Signed, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
171 /// Computes the index of the matrix component with the largest absolute value.
172 ///
173 /// # Examples:
174 ///
175 /// ```
176 /// # use nalgebra::Matrix2x3;
177 /// let mat = Matrix2x3::new(11, -12, 13,
178 /// 21, 22, -23);
179 /// assert_eq!(mat.iamax_full(), (1, 2));
180 /// ```
181 #[inline]
182 #[must_use]
183 pub fn iamax_full(&self) -> (usize, usize) {
184 assert!(!self.is_empty(), "The input matrix must not be empty.");
185
186 let mut the_max = unsafe { self.get_unchecked((0, 0)).abs() };
187 let mut the_ij = (0, 0);
188
189 for j in 0..self.ncols() {
190 for i in 0..self.nrows() {
191 let val = unsafe { self.get_unchecked((i, j)).abs() };
192
193 if val > the_max {
194 the_max = val;
195 the_ij = (i, j);
196 }
197 }
198 }
199
200 the_ij
201 }
202}
203
204// TODO: find a way to avoid code duplication just for complex number support.
205/// # Find the min and max components (vector-specific methods)
206impl<T: Scalar, D: Dim, S: RawStorage<T, D>> Vector<T, D, S> {
207 /// Computes the index of the vector component with the largest complex or real absolute value.
208 ///
209 /// # Examples:
210 ///
211 /// ```
212 /// # extern crate num_complex;
213 /// # extern crate nalgebra;
214 /// # use num_complex::Complex;
215 /// # use nalgebra::Vector3;
216 /// let vec = Vector3::new(Complex::new(11.0, 3.0), Complex::new(-15.0, 0.0), Complex::new(13.0, 5.0));
217 /// assert_eq!(vec.icamax(), 2);
218 /// ```
219 #[inline]
220 #[must_use]
221 pub fn icamax(&self) -> usize
222 where
223 T: ComplexField,
224 {
225 assert!(!self.is_empty(), "The input vector must not be empty.");
226
227 let mut the_max = unsafe { self.vget_unchecked(0).clone().norm1() };
228 let mut the_i = 0;
229
230 for i in 1..self.nrows() {
231 let val = unsafe { self.vget_unchecked(i).clone().norm1() };
232
233 if val > the_max {
234 the_max = val;
235 the_i = i;
236 }
237 }
238
239 the_i
240 }
241
242 /// Computes the index and value of the vector component with the largest value.
243 ///
244 /// # Examples:
245 ///
246 /// ```
247 /// # use nalgebra::Vector3;
248 /// let vec = Vector3::new(11, -15, 13);
249 /// assert_eq!(vec.argmax(), (2, 13));
250 /// ```
251 #[inline]
252 #[must_use]
253 pub fn argmax(&self) -> (usize, T)
254 where
255 T: PartialOrd,
256 {
257 assert!(!self.is_empty(), "The input vector must not be empty.");
258
259 let mut the_max = unsafe { self.vget_unchecked(0) };
260 let mut the_i = 0;
261
262 for i in 1..self.nrows() {
263 let val = unsafe { self.vget_unchecked(i) };
264
265 if val > the_max {
266 the_max = val;
267 the_i = i;
268 }
269 }
270
271 (the_i, the_max.clone())
272 }
273
274 /// Computes the index of the vector component with the largest value.
275 ///
276 /// # Examples:
277 ///
278 /// ```
279 /// # use nalgebra::Vector3;
280 /// let vec = Vector3::new(11, -15, 13);
281 /// assert_eq!(vec.imax(), 2);
282 /// ```
283 #[inline]
284 #[must_use]
285 pub fn imax(&self) -> usize
286 where
287 T: PartialOrd,
288 {
289 self.argmax().0
290 }
291
292 /// Computes the index of the vector component with the largest absolute value.
293 ///
294 /// # Examples:
295 ///
296 /// ```
297 /// # use nalgebra::Vector3;
298 /// let vec = Vector3::new(11, -15, 13);
299 /// assert_eq!(vec.iamax(), 1);
300 /// ```
301 #[inline]
302 #[must_use]
303 pub fn iamax(&self) -> usize
304 where
305 T: PartialOrd + Signed,
306 {
307 assert!(!self.is_empty(), "The input vector must not be empty.");
308
309 let mut the_max = unsafe { self.vget_unchecked(0).abs() };
310 let mut the_i = 0;
311
312 for i in 1..self.nrows() {
313 let val = unsafe { self.vget_unchecked(i).abs() };
314
315 if val > the_max {
316 the_max = val;
317 the_i = i;
318 }
319 }
320
321 the_i
322 }
323
324 /// Computes the index and value of the vector component with the smallest value.
325 ///
326 /// # Examples:
327 ///
328 /// ```
329 /// # use nalgebra::Vector3;
330 /// let vec = Vector3::new(11, -15, 13);
331 /// assert_eq!(vec.argmin(), (1, -15));
332 /// ```
333 #[inline]
334 #[must_use]
335 pub fn argmin(&self) -> (usize, T)
336 where
337 T: PartialOrd,
338 {
339 assert!(!self.is_empty(), "The input vector must not be empty.");
340
341 let mut the_min = unsafe { self.vget_unchecked(0) };
342 let mut the_i = 0;
343
344 for i in 1..self.nrows() {
345 let val = unsafe { self.vget_unchecked(i) };
346
347 if val < the_min {
348 the_min = val;
349 the_i = i;
350 }
351 }
352
353 (the_i, the_min.clone())
354 }
355
356 /// Computes the index of the vector component with the smallest value.
357 ///
358 /// # Examples:
359 ///
360 /// ```
361 /// # use nalgebra::Vector3;
362 /// let vec = Vector3::new(11, -15, 13);
363 /// assert_eq!(vec.imin(), 1);
364 /// ```
365 #[inline]
366 #[must_use]
367 pub fn imin(&self) -> usize
368 where
369 T: PartialOrd,
370 {
371 self.argmin().0
372 }
373
374 /// Computes the index of the vector component with the smallest absolute value.
375 ///
376 /// # Examples:
377 ///
378 /// ```
379 /// # use nalgebra::Vector3;
380 /// let vec = Vector3::new(11, -15, 13);
381 /// assert_eq!(vec.iamin(), 0);
382 /// ```
383 #[inline]
384 #[must_use]
385 pub fn iamin(&self) -> usize
386 where
387 T: PartialOrd + Signed,
388 {
389 assert!(!self.is_empty(), "The input vector must not be empty.");
390
391 let mut the_min = unsafe { self.vget_unchecked(0).abs() };
392 let mut the_i = 0;
393
394 for i in 1..self.nrows() {
395 let val = unsafe { self.vget_unchecked(i).abs() };
396
397 if val < the_min {
398 the_min = val;
399 the_i = i;
400 }
401 }
402
403 the_i
404 }
405}