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}