Skip to main content

malachite_nz/integer_vector/arithmetic/
div_exact.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::integer::Integer;
10use crate::integer_vector::IntegerVector;
11use crate::natural::Natural;
12use malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign, NegAssign};
13use malachite_base::num::basic::traits::{One, Zero};
14
15impl DivExact<Integer> for IntegerVector {
16    type Output = Self;
17
18    /// Divides every element of an [`IntegerVector`] by an [`Integer`], taking the vector by value
19    /// and the Integer by value. Every element must be exactly divisible by the [`Integer`].
20    ///
21    /// If some element is not exactly divisible by `c`, this function may panic or return a
22    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
23    /// it.
24    ///
25    /// $f(v, c) = v/c$.
26    ///
27    /// # Worst-case complexity
28    /// $T(n) = O(n \log n \log\log n)$
29    ///
30    /// $M(n) = O(n \log n)$
31    ///
32    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
33    /// elements and of `c`.
34    ///
35    /// # Panics
36    /// Panics if `c` is zero.
37    ///
38    /// # Examples
39    /// See [here](super::div_exact#div_exact).
40    ///
41    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
42    /// FLINT 3.6.0.
43    #[inline]
44    fn div_exact(mut self, c: Integer) -> Self {
45        self.div_exact_assign(&c);
46        self
47    }
48}
49
50impl DivExact<&Integer> for IntegerVector {
51    type Output = Self;
52
53    /// Divides every element of an [`IntegerVector`] by an [`Integer`], taking the vector by value
54    /// and the Integer by reference. Every element must be exactly divisible by the [`Integer`].
55    ///
56    /// If some element is not exactly divisible by `c`, this function may panic or return a
57    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
58    /// it.
59    ///
60    /// $f(v, c) = v/c$.
61    ///
62    /// # Worst-case complexity
63    /// $T(n) = O(n \log n \log\log n)$
64    ///
65    /// $M(n) = O(n \log n)$
66    ///
67    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
68    /// elements and of `c`.
69    ///
70    /// # Panics
71    /// Panics if `c` is zero.
72    ///
73    /// # Examples
74    /// See [here](super::div_exact#div_exact).
75    ///
76    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
77    /// FLINT 3.6.0.
78    #[inline]
79    fn div_exact(mut self, c: &Integer) -> Self {
80        self.div_exact_assign(c);
81        self
82    }
83}
84
85impl DivExact<Integer> for &IntegerVector {
86    type Output = IntegerVector;
87
88    /// Divides every element of an [`IntegerVector`] by an [`Integer`], taking the vector by
89    /// reference and the Integer by value. Every element must be exactly divisible by the
90    /// [`Integer`].
91    ///
92    /// If some element is not exactly divisible by `c`, this function may panic or return a
93    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
94    /// it.
95    ///
96    /// $f(v, c) = v/c$.
97    ///
98    /// # Worst-case complexity
99    /// $T(n) = O(n \log n \log\log n)$
100    ///
101    /// $M(n) = O(n \log n)$
102    ///
103    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
104    /// elements and of `c`.
105    ///
106    /// # Panics
107    /// Panics if `c` is zero.
108    ///
109    /// # Examples
110    /// See [here](super::div_exact#div_exact).
111    ///
112    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
113    /// FLINT 3.6.0.
114    #[inline]
115    fn div_exact(self, c: Integer) -> IntegerVector {
116        self.div_exact(&c)
117    }
118}
119
120impl DivExact<&Integer> for &IntegerVector {
121    type Output = IntegerVector;
122
123    /// Divides every element of an [`IntegerVector`] by an [`Integer`], taking the vector by
124    /// reference and the Integer by reference. Every element must be exactly divisible by the
125    /// [`Integer`].
126    ///
127    /// If some element is not exactly divisible by `c`, this function may panic or return a
128    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
129    /// it.
130    ///
131    /// $f(v, c) = v/c$.
132    ///
133    /// # Worst-case complexity
134    /// $T(n) = O(n \log n \log\log n)$
135    ///
136    /// $M(n) = O(n \log n)$
137    ///
138    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
139    /// elements and of `c`.
140    ///
141    /// # Panics
142    /// Panics if `c` is zero.
143    ///
144    /// # Examples
145    /// See [here](super::div_exact#div_exact).
146    ///
147    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
148    /// FLINT 3.6.0.
149    fn div_exact(self, c: &Integer) -> IntegerVector {
150        IntegerVector {
151            elements: match *c {
152                integer_zero!() => panic!("division by zero"),
153                integer_one!() => self.elements.clone(),
154                integer_negative_one!() => self.elements.iter().map(|x| -x).collect(),
155                _ => self.elements.iter().map(|x| x.div_exact(c)).collect(),
156            },
157        }
158    }
159}
160
161impl DivExactAssign<Integer> for IntegerVector {
162    /// Divides every element of an [`IntegerVector`] by an [`Integer`], in place, taking the
163    /// Integer by value. Every element must be exactly divisible by the [`Integer`].
164    ///
165    /// If some element is not exactly divisible by `c`, this function may panic or return a
166    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
167    /// it.
168    ///
169    /// $v \gets v/c$.
170    ///
171    /// # Worst-case complexity
172    /// $T(n) = O(n \log n \log\log n)$
173    ///
174    /// $M(n) = O(n \log n)$
175    ///
176    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
177    /// elements and of `c`.
178    ///
179    /// # Panics
180    /// Panics if `c` is zero.
181    ///
182    /// # Examples
183    /// See [here](super::div_exact#div_exact_assign).
184    ///
185    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
186    /// FLINT 3.6.0.
187    #[inline]
188    fn div_exact_assign(&mut self, c: Integer) {
189        self.div_exact_assign(&c);
190    }
191}
192
193impl DivExactAssign<&Integer> for IntegerVector {
194    /// Divides every element of an [`IntegerVector`] by an [`Integer`], in place, taking the
195    /// Integer by reference. Every element must be exactly divisible by the [`Integer`].
196    ///
197    /// If some element is not exactly divisible by `c`, this function may panic or return a
198    /// meaningless result. Dividing by 1 returns the vector unchanged, and dividing by $-1$ negates
199    /// it.
200    ///
201    /// $v \gets v/c$.
202    ///
203    /// # Worst-case complexity
204    /// $T(n) = O(n \log n \log\log n)$
205    ///
206    /// $M(n) = O(n \log n)$
207    ///
208    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
209    /// elements and of `c`.
210    ///
211    /// # Panics
212    /// Panics if `c` is zero.
213    ///
214    /// # Examples
215    /// See [here](super::div_exact#div_exact_assign).
216    ///
217    /// This is equivalent to `_fmpz_vec_scalar_divexact_fmpz` from `fmpz_vec/scalar_divexact.c`,
218    /// FLINT 3.6.0.
219    fn div_exact_assign(&mut self, c: &Integer) {
220        match *c {
221            integer_zero!() => panic!("division by zero"),
222            integer_one!() => {}
223            integer_negative_one!() => {
224                for x in &mut self.elements {
225                    x.neg_assign();
226                }
227            }
228            _ => {
229                for x in &mut self.elements {
230                    x.div_exact_assign(c);
231                }
232            }
233        }
234    }
235}