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}