malachite_base/unsigned_vector/comparison/entrywise_max.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::{EntrywiseMax, EntrywiseMaxAssign};
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11use crate::unsigned_vector::UnsignedVector;
12use core::cmp::max;
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 maximum of vectors of different dimensions"
19 );
20}
21
22impl<T: PrimitiveUnsigned> EntrywiseMax<Self> for UnsignedVector<T> {
23 type Output = Self;
24
25 /// Takes the entrywise maximum of two [`UnsignedVector`]s, taking the first by value and the
26 /// second by value.
27 ///
28 /// Every element of the result is the larger of the corresponding elements of the two vectors,
29 /// so the result has the same dimension as both.
30 ///
31 /// $$
32 /// f(v, w) = (\max(v_0, w_0), \max(v_1, w_1), \ldots, \max(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::EntrywiseMax;
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_max(w).to_string(), "(4, 5, 3)");
55 /// ```
56 #[inline]
57 fn entrywise_max(mut self, other: Self) -> Self {
58 self.entrywise_max_assign(other);
59 self
60 }
61}
62
63impl<T: PrimitiveUnsigned> EntrywiseMax<&Self> for UnsignedVector<T> {
64 type Output = Self;
65
66 /// Takes the entrywise maximum of two [`UnsignedVector`]s, taking the first by value and the
67 /// second by reference.
68 ///
69 /// See the documentation for the [`EntrywiseMax`] 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::EntrywiseMax;
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_max(&w).to_string(), "(4, 5, 3)");
92 /// ```
93 #[inline]
94 fn entrywise_max(mut self, other: &Self) -> Self {
95 self.entrywise_max_assign(other);
96 self
97 }
98}
99
100impl<T: PrimitiveUnsigned> EntrywiseMax<UnsignedVector<T>> for &UnsignedVector<T> {
101 type Output = UnsignedVector<T>;
102
103 /// Takes the entrywise maximum of two [`UnsignedVector`]s, taking the first by reference and
104 /// the second by value.
105 ///
106 /// See the documentation for the [`EntrywiseMax`] 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::EntrywiseMax;
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_max(w).to_string(), "(4, 5, 3)");
129 /// ```
130 #[inline]
131 fn entrywise_max(self, mut other: UnsignedVector<T>) -> UnsignedVector<T> {
132 // The maximum is symmetric, so the owned vector can hold the result.
133 other.entrywise_max_assign(self);
134 other
135 }
136}
137
138impl<T: PrimitiveUnsigned> EntrywiseMax<&UnsignedVector<T>> for &UnsignedVector<T> {
139 type Output = UnsignedVector<T>;
140
141 /// Takes the entrywise maximum of two [`UnsignedVector`]s, taking the first by reference and
142 /// the second by reference.
143 ///
144 /// See the documentation for the [`EntrywiseMax`] 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::EntrywiseMax;
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_max(&w).to_string(), "(4, 5, 3)");
167 /// ```
168 fn entrywise_max(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)| max(x, y))
176 .collect(),
177 }
178 }
179}
180
181impl<T: PrimitiveUnsigned> EntrywiseMaxAssign<Self> for UnsignedVector<T> {
182 /// Replaces an [`UnsignedVector`] by its entrywise maximum with another [`UnsignedVector`],
183 /// taking the other by value.
184 ///
185 /// Every element becomes the larger 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::EntrywiseMaxAssign;
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_max_assign(w);
207 /// assert_eq!(v.to_string(), "(4, 5, 3)");
208 /// ```
209 fn entrywise_max_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> EntrywiseMaxAssign<&Self> for UnsignedVector<T> {
220 /// Replaces an [`UnsignedVector`] by its entrywise maximum with another [`UnsignedVector`],
221 /// taking the other by reference.
222 ///
223 /// Every element becomes the larger 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::EntrywiseMaxAssign;
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_max_assign(&w);
245 /// assert_eq!(v.to_string(), "(4, 5, 3)");
246 /// ```
247 fn entrywise_max_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}