Skip to main content

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