Skip to main content

malachite_base/unsigned_vector/arithmetic/
entrywise_div_round.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::{EntrywiseDivRound, EntrywiseDivRoundAssign};
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11use crate::rounding_modes::RoundingMode;
12use crate::unsigned_vector::UnsignedVector;
13
14impl<T: PrimitiveUnsigned> EntrywiseDivRound<T> for UnsignedVector<T> {
15    type Output = Self;
16
17    /// Divides every element of an [`UnsignedVector`] by a `T`, taking it by value, and rounds
18    /// every quotient according to the specified rounding mode.
19    ///
20    /// Each quotient is rounded as by [`DivRound`](crate::num::arithmetic::traits::DivRound), but
21    /// no [`Ordering`](core::cmp::Ordering) is returned, since with `Nearest` different elements
22    /// may be rounded in different directions. Passing `Floor` or `Down` is equivalent to using
23    /// `/`.
24    ///
25    /// $f(v, c, r)_i = \operatorname{round}(v_i/c)$, where $\operatorname{round}$ rounds according
26    /// to `rm`.
27    ///
28    /// # Worst-case complexity
29    /// $T(n) = O(n)$
30    ///
31    /// $M(n) = O(1)$
32    ///
33    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
34    ///
35    /// # Panics
36    /// Panics if `c` is zero, or if `rm` is `Exact` and some element is not divisible by `c`.
37    ///
38    /// # Examples
39    /// See [here](super::entrywise_div_round#entrywise_div_round).
40    #[inline]
41    fn entrywise_div_round(mut self, c: T, rm: RoundingMode) -> Self {
42        self.entrywise_div_round_assign(c, rm);
43        self
44    }
45}
46
47impl<T: PrimitiveUnsigned> EntrywiseDivRound<T> for &UnsignedVector<T> {
48    type Output = UnsignedVector<T>;
49
50    /// Divides every element of an [`UnsignedVector`] by a `T`, taking it by reference, and rounds
51    /// every quotient according to the specified rounding mode.
52    ///
53    /// Each quotient is rounded as by [`DivRound`](crate::num::arithmetic::traits::DivRound), but
54    /// no [`Ordering`](core::cmp::Ordering) is returned, since with `Nearest` different elements
55    /// may be rounded in different directions. Passing `Floor` or `Down` is equivalent to using
56    /// `/`.
57    ///
58    /// $f(v, c, r)_i = \operatorname{round}(v_i/c)$, where $\operatorname{round}$ rounds according
59    /// to `rm`.
60    ///
61    /// # Worst-case complexity
62    /// $T(n) = O(n)$
63    ///
64    /// $M(n) = O(n)$
65    ///
66    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
67    ///
68    /// # Panics
69    /// Panics if `c` is zero, or if `rm` is `Exact` and some element is not divisible by `c`.
70    ///
71    /// # Examples
72    /// See [here](super::entrywise_div_round#entrywise_div_round).
73    fn entrywise_div_round(self, c: T, rm: RoundingMode) -> UnsignedVector<T> {
74        assert!(c != T::ZERO, "division by zero");
75        UnsignedVector {
76            elements: if c == T::ONE {
77                self.elements.clone()
78            } else {
79                self.elements
80                    .iter()
81                    .map(|&x| x.div_round(c, rm).0)
82                    .collect()
83            },
84        }
85    }
86}
87
88impl<T: PrimitiveUnsigned> EntrywiseDivRoundAssign<T> for UnsignedVector<T> {
89    /// Divides every element of an [`UnsignedVector`] by a `T`, in place, and rounds every quotient
90    /// according to the specified rounding mode.
91    ///
92    /// Each quotient is rounded as by [`DivRound`](crate::num::arithmetic::traits::DivRound), but
93    /// no [`Ordering`](core::cmp::Ordering) is returned, since with `Nearest` different elements
94    /// may be rounded in different directions. Passing `Floor` or `Down` is equivalent to using
95    /// `/`.
96    ///
97    /// $v_i \gets \operatorname{round}(v_i/c)$, where $\operatorname{round}$ rounds according to
98    /// `rm`.
99    ///
100    /// # Worst-case complexity
101    /// $T(n) = O(n)$
102    ///
103    /// $M(n) = O(1)$
104    ///
105    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.dimension()`.
106    ///
107    /// # Panics
108    /// Panics if `c` is zero, or if `rm` is `Exact` and some element is not divisible by `c`.
109    ///
110    /// # Examples
111    /// See [here](super::entrywise_div_round#entrywise_div_round_assign).
112    fn entrywise_div_round_assign(&mut self, c: T, rm: RoundingMode) {
113        assert!(c != T::ZERO, "division by zero");
114        if c != T::ONE {
115            for x in &mut self.elements {
116                x.div_round_assign(c, rm);
117            }
118        }
119    }
120}