Skip to main content

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);