Skip to main content

malachite_base/unsigned_vector/comparison/
entrywise_min.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{EntrywiseMin, EntrywiseMinAssign};
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11use crate::unsigned_vector::UnsignedVector;
12use core::cmp::min;
13
14fn assert_same_dimension<T: PrimitiveUnsigned>(v: &UnsignedVector<T>, w: &UnsignedVector<T>) {
15    assert_eq!(
16        v.elements.len(),
17        w.elements.len(),
18        "cannot take the entrywise minimum of vectors of different dimensions"
19    );
20}
21
22impl<T: PrimitiveUnsigned> EntrywiseMin<Self> for UnsignedVector<T> {
23    type Output = Self;
24
25    /// Takes the entrywise minimum of two [`UnsignedVector`]s, taking the first by value and the
26    /// second by value.
27    ///
28    /// Every element of the result is the smaller of the corresponding elements of the two vectors,
29    /// so the result has the same dimension as both.
30    ///
31    /// $$
32    /// f(v, w) = (\min(v_0, w_0), \min(v_1, w_1), \ldots, \min(v_{n-1}, w_{n-1})).
33    /// $$
34    ///
35    /// # Worst-case complexity
36    /// $T(n) = O(n)$
37    ///
38    /// $M(n) = O(1)$
39    ///
40    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
41    /// elements of both vectors.
42    ///
43    /// # Panics
44    /// Panics if `self` and `other` have different dimensions.
45    ///
46    /// # Examples
47    /// ```
48    /// use core::str::FromStr;
49    /// use malachite_base::num::arithmetic::traits::EntrywiseMin;
50    /// use malachite_base::unsigned_vector::UnsignedVector;
51    ///
52    /// let v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
53    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
54    /// assert_eq!(v.entrywise_min(w).to_string(), "(1, 2, 3)");
55    /// ```
56    #[inline]
57    fn entrywise_min(mut self, other: Self) -> Self {
58        self.entrywise_min_assign(other);
59        self
60    }
61}
62
63impl<T: PrimitiveUnsigned> EntrywiseMin<&Self> for UnsignedVector<T> {
64    type Output = Self;
65
66    /// Takes the entrywise minimum of two [`UnsignedVector`]s, taking the first by value and the
67    /// second by reference.
68    ///
69    /// See the documentation for the [`EntrywiseMin`] implementation that takes both vectors by
70    /// value for details.
71    ///
72    /// # Worst-case complexity
73    /// $T(n) = O(n)$
74    ///
75    /// $M(n) = O(1)$
76    ///
77    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
78    /// elements of both vectors.
79    ///
80    /// # Panics
81    /// Panics if `self` and `other` have different dimensions.
82    ///
83    /// # Examples
84    /// ```
85    /// use core::str::FromStr;
86    /// use malachite_base::num::arithmetic::traits::EntrywiseMin;
87    /// use malachite_base::unsigned_vector::UnsignedVector;
88    ///
89    /// let v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
90    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
91    /// assert_eq!(v.entrywise_min(&w).to_string(), "(1, 2, 3)");
92    /// ```
93    #[inline]
94    fn entrywise_min(mut self, other: &Self) -> Self {
95        self.entrywise_min_assign(other);
96        self
97    }
98}
99
100impl<T: PrimitiveUnsigned> EntrywiseMin<UnsignedVector<T>> for &UnsignedVector<T> {
101    type Output = UnsignedVector<T>;
102
103    /// Takes the entrywise minimum of two [`UnsignedVector`]s, taking the first by reference and
104    /// the second by value.
105    ///
106    /// See the documentation for the [`EntrywiseMin`] implementation that takes both vectors by
107    /// value for details.
108    ///
109    /// # Worst-case complexity
110    /// $T(n) = O(n)$
111    ///
112    /// $M(n) = O(1)$
113    ///
114    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
115    /// elements of both vectors.
116    ///
117    /// # Panics
118    /// Panics if `self` and `other` have different dimensions.
119    ///
120    /// # Examples
121    /// ```
122    /// use core::str::FromStr;
123    /// use malachite_base::num::arithmetic::traits::EntrywiseMin;
124    /// use malachite_base::unsigned_vector::UnsignedVector;
125    ///
126    /// let v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
127    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
128    /// assert_eq!((&v).entrywise_min(w).to_string(), "(1, 2, 3)");
129    /// ```
130    #[inline]
131    fn entrywise_min(self, mut other: UnsignedVector<T>) -> UnsignedVector<T> {
132        // The minimum is symmetric, so the owned vector can hold the result.
133        other.entrywise_min_assign(self);
134        other
135    }
136}
137
138impl<T: PrimitiveUnsigned> EntrywiseMin<&UnsignedVector<T>> for &UnsignedVector<T> {
139    type Output = UnsignedVector<T>;
140
141    /// Takes the entrywise minimum of two [`UnsignedVector`]s, taking the first by reference and
142    /// the second by reference.
143    ///
144    /// See the documentation for the [`EntrywiseMin`] implementation that takes both vectors by
145    /// value for details.
146    ///
147    /// # Worst-case complexity
148    /// $T(n) = O(n)$
149    ///
150    /// $M(n) = O(n)$
151    ///
152    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
153    /// elements of both vectors.
154    ///
155    /// # Panics
156    /// Panics if `self` and `other` have different dimensions.
157    ///
158    /// # Examples
159    /// ```
160    /// use core::str::FromStr;
161    /// use malachite_base::num::arithmetic::traits::EntrywiseMin;
162    /// use malachite_base::unsigned_vector::UnsignedVector;
163    ///
164    /// let v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
165    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
166    /// assert_eq!((&v).entrywise_min(&w).to_string(), "(1, 2, 3)");
167    /// ```
168    fn entrywise_min(self, other: &UnsignedVector<T>) -> UnsignedVector<T> {
169        assert_same_dimension(self, other);
170        UnsignedVector {
171            elements: self
172                .elements
173                .iter()
174                .zip(&other.elements)
175                .map(|(&x, &y)| min(x, y))
176                .collect(),
177        }
178    }
179}
180
181impl<T: PrimitiveUnsigned> EntrywiseMinAssign<Self> for UnsignedVector<T> {
182    /// Replaces an [`UnsignedVector`] by its entrywise minimum with another [`UnsignedVector`],
183    /// taking the other by value.
184    ///
185    /// Every element becomes the smaller of itself and the corresponding element of `other`.
186    ///
187    /// # Worst-case complexity
188    /// $T(n) = O(n)$
189    ///
190    /// $M(n) = O(1)$
191    ///
192    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
193    /// elements of both vectors.
194    ///
195    /// # Panics
196    /// Panics if `self` and `other` have different dimensions.
197    ///
198    /// # Examples
199    /// ```
200    /// use core::str::FromStr;
201    /// use malachite_base::num::arithmetic::traits::EntrywiseMinAssign;
202    /// use malachite_base::unsigned_vector::UnsignedVector;
203    ///
204    /// let mut v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
205    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
206    /// v.entrywise_min_assign(w);
207    /// assert_eq!(v.to_string(), "(1, 2, 3)");
208    /// ```
209    fn entrywise_min_assign(&mut self, other: Self) {
210        assert_same_dimension(self, &other);
211        for (x, y) in self.elements.iter_mut().zip(other.elements) {
212            if y < *x {
213                *x = y;
214            }
215        }
216    }
217}
218
219impl<T: PrimitiveUnsigned> EntrywiseMinAssign<&Self> for UnsignedVector<T> {
220    /// Replaces an [`UnsignedVector`] by its entrywise minimum with another [`UnsignedVector`],
221    /// taking the other by reference.
222    ///
223    /// Every element becomes the smaller of itself and the corresponding element of `other`.
224    ///
225    /// # Worst-case complexity
226    /// $T(n) = O(n)$
227    ///
228    /// $M(n) = O(n)$
229    ///
230    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
231    /// elements of both vectors.
232    ///
233    /// # Panics
234    /// Panics if `self` and `other` have different dimensions.
235    ///
236    /// # Examples
237    /// ```
238    /// use core::str::FromStr;
239    /// use malachite_base::num::arithmetic::traits::EntrywiseMinAssign;
240    /// use malachite_base::unsigned_vector::UnsignedVector;
241    ///
242    /// let mut v = UnsignedVector::<u8>::from_str("(1, 5, 3)").unwrap();
243    /// let w = UnsignedVector::<u8>::from_str("(4, 2, 3)").unwrap();
244    /// v.entrywise_min_assign(&w);
245    /// assert_eq!(v.to_string(), "(1, 2, 3)");
246    /// ```
247    fn entrywise_min_assign(&mut self, other: &Self) {
248        assert_same_dimension(self, other);
249        for (x, &y) in self.elements.iter_mut().zip(&other.elements) {
250            if y < *x {
251                *x = y;
252            }
253        }
254    }
255}