malachite_nz/integer_vector/arithmetic/shl.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 core::ops::{Shl, ShlAssign};
12
13// Shifts every element left by `bits`.
14fn shl_ref<T: Copy>(v: &IntegerVector, bits: T) -> IntegerVector
15where
16 for<'a> &'a Integer: Shl<T, Output = Integer>,
17{
18 IntegerVector {
19 elements: v.elements.iter().map(|x| x << bits).collect(),
20 }
21}
22
23// Shifts every element left by `bits`, in place.
24fn shl_assign<T: Copy>(v: &mut IntegerVector, bits: T)
25where
26 Integer: ShlAssign<T>,
27{
28 for x in &mut v.elements {
29 *x <<= bits;
30 }
31}
32
33macro_rules! impl_integer_vector_shl_unsigned {
34 ($t:ident) => {
35 impl Shl<$t> for IntegerVector {
36 type Output = IntegerVector;
37
38 /// Left-shifts an [`IntegerVector`] (multiplies it by a power of 2), taking it by
39 /// value. Every element is shifted, and the dimension is unchanged.
40 ///
41 /// $f(v, k) = 2^kv$.
42 ///
43 /// # Worst-case complexity
44 /// $T(n, m, k) = O(n + km)$
45 ///
46 /// $M(n, m, k) = O(n + km)$
47 ///
48 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
49 /// elements, $m$ is `bits`, and $k$ is `self.dimension()`.
50 ///
51 /// # Examples
52 /// See [here](super::shl#shl).
53 ///
54 /// This is equivalent to `_fmpz_vec_scalar_mul_2exp` from `fmpz_vec/scalar.c`, FLINT
55 /// 3.6.0.
56 #[inline]
57 fn shl(mut self, bits: $t) -> IntegerVector {
58 self <<= bits;
59 self
60 }
61 }
62
63 impl Shl<$t> for &IntegerVector {
64 type Output = IntegerVector;
65
66 /// Left-shifts an [`IntegerVector`] (multiplies it by a power of 2), taking it by
67 /// reference. Every element is shifted, and the dimension is unchanged.
68 ///
69 /// $f(v, k) = 2^kv$.
70 ///
71 /// # Worst-case complexity
72 /// $T(n, m, k) = O(n + km)$
73 ///
74 /// $M(n, m, k) = O(n + km)$
75 ///
76 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
77 /// elements, $m$ is `bits`, and $k$ is `self.dimension()`.
78 ///
79 /// # Examples
80 /// See [here](super::shl#shl).
81 ///
82 /// This is equivalent to `_fmpz_vec_scalar_mul_2exp` from `fmpz_vec/scalar.c`, FLINT
83 /// 3.6.0.
84 #[inline]
85 fn shl(self, bits: $t) -> IntegerVector {
86 shl_ref(self, bits)
87 }
88 }
89
90 impl ShlAssign<$t> for IntegerVector {
91 /// Left-shifts an [`IntegerVector`] (multiplies it by a power of 2), in place. Every
92 /// element is shifted, and the dimension is unchanged.
93 ///
94 /// $v \gets 2^kv$.
95 ///
96 /// # Worst-case complexity
97 /// $T(n, m, k) = O(n + km)$
98 ///
99 /// $M(n, m, k) = O(n + km)$
100 ///
101 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
102 /// elements, $m$ is `bits`, and $k$ is `self.dimension()`.
103 ///
104 /// # Examples
105 /// See [here](super::shl#shl_assign).
106 ///
107 /// This is equivalent to `_fmpz_vec_scalar_mul_2exp` from `fmpz_vec/scalar.c`, FLINT
108 /// 3.6.0.
109 #[inline]
110 fn shl_assign(&mut self, bits: $t) {
111 shl_assign(self, bits);
112 }
113 }
114 };
115}
116apply_to_unsigneds!(impl_integer_vector_shl_unsigned);
117
118macro_rules! impl_integer_vector_shl_signed {
119 ($t:ident) => {
120 impl Shl<$t> for IntegerVector {
121 type Output = IntegerVector;
122
123 /// Left-shifts an [`IntegerVector`] (multiplies or divides it by a power of 2), taking
124 /// it by value. Every element is shifted, and the dimension is unchanged.
125 ///
126 /// $f(v, k) = 2^kv$.
127 ///
128 /// A negative `bits` shifts right, rounding every element down (toward negative
129 /// infinity); to round differently, use
130 /// [`entrywise_shl_round`](malachite_base::num::arithmetic::traits::EntrywiseShlRound).
131 ///
132 /// # Worst-case complexity
133 /// $T(n, m, k) = O(n + km)$
134 ///
135 /// $M(n, m, k) = O(n + km)$
136 ///
137 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
138 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
139 ///
140 /// # Examples
141 /// See [here](super::shl#shl).
142 #[inline]
143 fn shl(mut self, bits: $t) -> IntegerVector {
144 self <<= bits;
145 self
146 }
147 }
148
149 impl Shl<$t> for &IntegerVector {
150 type Output = IntegerVector;
151
152 /// Left-shifts an [`IntegerVector`] (multiplies or divides it by a power of 2), taking
153 /// it by reference. Every element is shifted, and the dimension is unchanged.
154 ///
155 /// $f(v, k) = 2^kv$.
156 ///
157 /// A negative `bits` shifts right, rounding every element down (toward negative
158 /// infinity); to round differently, use
159 /// [`entrywise_shl_round`](malachite_base::num::arithmetic::traits::EntrywiseShlRound).
160 ///
161 /// # Worst-case complexity
162 /// $T(n, m, k) = O(n + km)$
163 ///
164 /// $M(n, m, k) = O(n + km)$
165 ///
166 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
167 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
168 ///
169 /// # Examples
170 /// See [here](super::shl#shl).
171 #[inline]
172 fn shl(self, bits: $t) -> IntegerVector {
173 shl_ref(self, bits)
174 }
175 }
176
177 impl ShlAssign<$t> for IntegerVector {
178 /// Left-shifts an [`IntegerVector`] (multiplies or divides it by a power of 2), in
179 /// place. Every element is shifted, and the dimension is unchanged.
180 ///
181 /// $v \gets 2^kv$.
182 ///
183 /// A negative `bits` shifts right, rounding every element down (toward negative
184 /// infinity); to round differently, use
185 /// [`entrywise_shl_round`](malachite_base::num::arithmetic::traits::EntrywiseShlRound).
186 ///
187 /// # Worst-case complexity
188 /// $T(n, m, k) = O(n + km)$
189 ///
190 /// $M(n, m, k) = O(n + km)$
191 ///
192 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
193 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
194 ///
195 /// # Examples
196 /// See [here](super::shl#shl_assign).
197 #[inline]
198 fn shl_assign(&mut self, bits: $t) {
199 shl_assign(self, bits);
200 }
201 }
202 };
203}
204apply_to_signeds!(impl_integer_vector_shl_signed);