Skip to main content

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