malachite_q/rational_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::Rational;
10use crate::rational_vector::RationalVector;
11use core::ops::{Shl, ShlAssign};
12
13// Shifts every element left by `bits`.
14fn shl_ref<T: Copy>(v: &RationalVector, bits: T) -> RationalVector
15where
16 for<'a> &'a Rational: Shl<T, Output = Rational>,
17{
18 RationalVector {
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 RationalVector, bits: T)
25where
26 Rational: ShlAssign<T>,
27{
28 for x in &mut v.elements {
29 *x <<= bits;
30 }
31}
32
33macro_rules! impl_rational_vector_shl_unsigned {
34 ($t:ident) => {
35 impl Shl<$t> for RationalVector {
36 type Output = RationalVector;
37
38 /// Left-shifts a [`RationalVector`] (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 #[inline]
54 fn shl(mut self, bits: $t) -> RationalVector {
55 self <<= bits;
56 self
57 }
58 }
59
60 impl Shl<$t> for &RationalVector {
61 type Output = RationalVector;
62
63 /// Left-shifts a [`RationalVector`] (multiplies it by a power of 2), taking it by
64 /// reference. Every element is shifted, and the dimension is unchanged.
65 ///
66 /// $f(v, k) = 2^kv$.
67 ///
68 /// # Worst-case complexity
69 /// $T(n, m, k) = O(n + km)$
70 ///
71 /// $M(n, m, k) = O(n + km)$
72 ///
73 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
74 /// elements, $m$ is `bits`, and $k$ is `self.dimension()`.
75 ///
76 /// # Examples
77 /// See [here](super::shl#shl).
78 #[inline]
79 fn shl(self, bits: $t) -> RationalVector {
80 shl_ref(self, bits)
81 }
82 }
83
84 impl ShlAssign<$t> for RationalVector {
85 /// Left-shifts a [`RationalVector`] (multiplies it by a power of 2), in place. Every
86 /// element is shifted, and the dimension is unchanged.
87 ///
88 /// $v \gets 2^kv$.
89 ///
90 /// # Worst-case complexity
91 /// $T(n, m, k) = O(n + km)$
92 ///
93 /// $M(n, m, k) = O(n + km)$
94 ///
95 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
96 /// elements, $m$ is `bits`, and $k$ is `self.dimension()`.
97 ///
98 /// # Examples
99 /// See [here](super::shl#shl_assign).
100 #[inline]
101 fn shl_assign(&mut self, bits: $t) {
102 shl_assign(self, bits);
103 }
104 }
105 };
106}
107apply_to_unsigneds!(impl_rational_vector_shl_unsigned);
108
109macro_rules! impl_rational_vector_shl_signed {
110 ($t:ident) => {
111 impl Shl<$t> for RationalVector {
112 type Output = RationalVector;
113
114 /// Left-shifts a [`RationalVector`] (multiplies it by a power of 2), taking it by
115 /// value. Every element is shifted, and the dimension is unchanged.
116 ///
117 /// $f(v, k) = 2^kv$.
118 ///
119 /// A negative `bits` shifts right, dividing every element by $2^{-k}$; each element
120 /// stays in lowest terms.
121 ///
122 /// # Worst-case complexity
123 /// $T(n, m, k) = O(n + km)$
124 ///
125 /// $M(n, m, k) = O(n + km)$
126 ///
127 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
128 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
129 ///
130 /// # Examples
131 /// See [here](super::shl#shl).
132 #[inline]
133 fn shl(mut self, bits: $t) -> RationalVector {
134 self <<= bits;
135 self
136 }
137 }
138
139 impl Shl<$t> for &RationalVector {
140 type Output = RationalVector;
141
142 /// Left-shifts a [`RationalVector`] (multiplies it by a power of 2), taking it by
143 /// reference. Every element is shifted, and the dimension is unchanged.
144 ///
145 /// $f(v, k) = 2^kv$.
146 ///
147 /// A negative `bits` shifts right, dividing every element by $2^{-k}$; each element
148 /// stays in lowest terms.
149 ///
150 /// # Worst-case complexity
151 /// $T(n, m, k) = O(n + km)$
152 ///
153 /// $M(n, m, k) = O(n + km)$
154 ///
155 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
156 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
157 ///
158 /// # Examples
159 /// See [here](super::shl#shl).
160 #[inline]
161 fn shl(self, bits: $t) -> RationalVector {
162 shl_ref(self, bits)
163 }
164 }
165
166 impl ShlAssign<$t> for RationalVector {
167 /// Left-shifts a [`RationalVector`] (multiplies it by a power of 2), in place. Every
168 /// element is shifted, and the dimension is unchanged.
169 ///
170 /// $v \gets 2^kv$.
171 ///
172 /// A negative `bits` shifts right, dividing every element by $2^{-k}$; each element
173 /// stays in lowest terms.
174 ///
175 /// # Worst-case complexity
176 /// $T(n, m, k) = O(n + km)$
177 ///
178 /// $M(n, m, k) = O(n + km)$
179 ///
180 /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
181 /// elements, $m$ is `bits.unsigned_abs()`, and $k$ is `self.dimension()`.
182 ///
183 /// # Examples
184 /// See [here](super::shl#shl_assign).
185 #[inline]
186 fn shl_assign(&mut self, bits: $t) {
187 shl_assign(self, bits);
188 }
189 }
190 };
191}
192apply_to_signeds!(impl_rational_vector_shl_signed);