malachite_base/num/logic/
bit_access.rs

1// Copyright © 2025 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::num::basic::signeds::PrimitiveSigned;
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11use crate::num::logic::traits::BitAccess;
12
13fn get_bit_unsigned<T: PrimitiveUnsigned>(x: &T, index: u64) -> bool {
14    index < T::WIDTH && (*x >> index).odd()
15}
16
17fn set_bit_unsigned<T: PrimitiveUnsigned>(x: &mut T, index: u64) {
18    if index < T::WIDTH {
19        *x |= T::power_of_2(index);
20    } else {
21        panic!(
22            "Cannot set bit {} in non-negative value of width {}",
23            index,
24            T::WIDTH
25        );
26    }
27}
28
29fn clear_bit_unsigned<T: PrimitiveUnsigned>(x: &mut T, index: u64) {
30    if index < T::WIDTH {
31        *x &= !T::power_of_2(index);
32    }
33}
34
35macro_rules! impl_bit_access_unsigned {
36    ($t:ident) => {
37        impl BitAccess for $t {
38            /// Determines whether the $i$th bit of an unsigned primitive integer, or the
39            /// coefficient of $2^i$ in its binary expansion, is 0 or 1.
40            ///
41            /// `false` means 0 and `true` means 1. Getting bits beyond the type's width is allowed;
42            /// those bits are false.
43            ///
44            /// Let
45            /// $$
46            /// n = \sum_{i=0}^\infty 2^{b_i},
47            /// $$
48            /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the
49            /// rest are 0. Then $f(n, j) = (b_j = 1)$.
50            ///
51            /// # Worst-case complexity
52            /// Constant time and additional memory.
53            ///
54            /// # Examples
55            /// See [here](super::bit_access#get_bit).
56            #[inline]
57            fn get_bit(&self, index: u64) -> bool {
58                get_bit_unsigned(self, index)
59            }
60
61            /// Sets the $i$th bit of an unsigned primitive integer, or the coefficient of $2^i$ in
62            /// its binary expansion, to 1.
63            ///
64            /// Setting bits beyond the type's width is disallowed.
65            ///
66            /// Let
67            /// $$
68            /// n = \sum_{i=0}^{W-1} 2^{b_i},
69            /// $$
70            /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then
71            /// $$
72            /// n \gets \\begin{cases}
73            ///     n + 2^j & \text{if} \\quad b_j = 0, \\\\
74            ///     n & \text{otherwise},
75            /// \\end{cases}
76            /// $$
77            /// where $j < W$.
78            ///
79            /// # Worst-case complexity
80            /// Constant time and additional memory.
81            ///
82            /// # Panics
83            /// Panics if $i \geq W$, where $i$ is `index` and $W$ is `$t::WIDTH`.
84            ///
85            /// # Examples
86            /// See [here](super::bit_access#set_bit).
87            #[inline]
88            fn set_bit(&mut self, index: u64) {
89                set_bit_unsigned(self, index)
90            }
91
92            /// Sets the $i$th bit of an unsigned primitive integer, or the coefficient of $2^i$ in
93            /// its binary expansion, to 0.
94            ///
95            /// Clearing bits beyond the type's width is allowed; since those bits are already
96            /// `false`, clearing them does nothing.
97            ///
98            /// Let
99            /// $$
100            /// n = \sum_{i=0}^{W-1} 2^{b_i},
101            /// $$
102            /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then
103            /// $$
104            /// n \gets \\begin{cases}
105            ///     n - 2^j & \text{if} \\quad b_j = 1, \\\\
106            ///     n & \text{otherwise}.
107            /// \\end{cases}
108            /// $$
109            ///
110            /// # Worst-case complexity
111            /// Constant time and additional memory.
112            ///
113            /// # Examples
114            /// See [here](super::bit_access#clear_bit).
115            #[inline]
116            fn clear_bit(&mut self, index: u64) {
117                clear_bit_unsigned(self, index)
118            }
119        }
120    };
121}
122apply_to_unsigneds!(impl_bit_access_unsigned);
123
124fn get_bit_signed<T: PrimitiveSigned>(x: &T, index: u64) -> bool {
125    if index < T::WIDTH {
126        (*x >> index).odd()
127    } else {
128        *x < T::ZERO
129    }
130}
131
132fn set_bit_signed<T: PrimitiveSigned>(x: &mut T, index: u64) {
133    if index < T::WIDTH {
134        *x |= T::ONE << index;
135    } else if *x >= T::ZERO {
136        panic!(
137            "Cannot set bit {} in non-negative value of width {}",
138            index,
139            T::WIDTH
140        );
141    }
142}
143
144fn clear_bit_signed<T: PrimitiveSigned>(x: &mut T, index: u64) {
145    if index < T::WIDTH {
146        *x &= !(T::ONE << index);
147    } else if *x < T::ZERO {
148        panic!(
149            "Cannot clear bit {} in negative value of width {}",
150            index,
151            T::WIDTH
152        );
153    }
154}
155
156macro_rules! impl_bit_access_signed {
157    ($t:ident) => {
158        impl BitAccess for $t {
159            /// Determines whether the $i$th bit of a signed primitive integer is 0 or 1.
160            ///
161            /// `false` means 0 and `true` means 1. Getting bits beyond the type's width is allowed;
162            /// those bits are `true` if the value is negative, and `false` otherwise.
163            ///
164            /// If $n \geq 0$, let
165            /// $$
166            /// n = \sum_{i=0}^\infty 2^{b_i},
167            /// $$
168            /// where for all $i$, $b_i\in \\{0, 1\\}$; so finitely many of the bits are 1, and the
169            /// rest are 0. Then $f(n, i) = (b_i = 1)$.
170            ///
171            /// If $n < 0$, let
172            /// $$
173            /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i},
174            /// $$
175            /// where
176            /// - $W$ is the type's width
177            /// - for all $i$, $b_i\in \\{0, 1\\}$, and $b_i = 1$ for $i \geq W$.
178            ///
179            /// Then $f(n, j) = (b_j = 1)$.
180            ///
181            /// # Worst-case complexity
182            /// Constant time and additional memory.
183            ///
184            /// # Examples
185            /// See [here](super::bit_access#get_bit).
186            #[inline]
187            fn get_bit(&self, index: u64) -> bool {
188                get_bit_signed(self, index)
189            }
190
191            /// Sets the $i$th bit of a signed primitive integer to 1.
192            ///
193            /// Setting bits beyond the type's width is disallowed if the number is non-negative.
194            ///
195            /// If $n \geq 0$ and $j \neq W - 1$, let
196            /// $$
197            /// n = \sum_{i=0}^{W-1} 2^{b_i};
198            /// $$
199            /// but if $n < 0$ or $j = W - 1$, let
200            /// $$
201            /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i},
202            /// $$
203            /// where for all $i$, $b_i\in \\{0, 1\\}$, and $W$ is the width of the type. Then
204            /// $$
205            /// n \gets \\begin{cases}
206            ///     n + 2^j & \text{if} \\quad b_j = 0, \\\\
207            ///     n & \text{otherwise},
208            /// \\end{cases}
209            /// $$
210            /// where $n < 0$ or $j < W$.
211            ///
212            /// # Worst-case complexity
213            /// Constant time and additional memory.
214            ///
215            /// # Panics
216            /// Panics if $n \geq 0$ and $i \geq W$, where $n$ is `self`, $i$ is `index` and $W$ is
217            /// the width of the type.
218            ///
219            /// # Examples
220            /// See [here](super::bit_access#set_bit).
221            #[inline]
222            fn set_bit(&mut self, index: u64) {
223                set_bit_signed(self, index)
224            }
225
226            /// Sets the $i$th bit of a signed primitive integer to 0.
227            ///
228            /// Clearing bits beyond the type's width is disallowed if the number is negative.
229            ///
230            /// If $n \geq 0$ or $j = W - 1$, let
231            /// $$
232            /// n = \sum_{i=0}^{W-1} 2^{b_i};
233            /// $$
234            /// but if $n < 0$ or $j = W - 1$, let
235            /// $$
236            /// 2^W + n = \sum_{i=0}^{W-1} 2^{b_i},
237            /// $$
238            /// where for all $i$, $b_i\in \\{0, 1\\}$ and $W$ is the width of the type. Then
239            /// $$
240            /// n \gets \\begin{cases}
241            ///     n - 2^j & \text{if} \\quad b_j = 1, \\\\
242            ///     n & \text{otherwise},
243            /// \\end{cases}
244            /// $$
245            /// where $n \geq 0$ or $j < W$.
246            ///
247            /// # Worst-case complexity
248            /// Constant time and additional memory.
249            ///
250            /// # Panics
251            /// Panics if $n < 0$ and $i \geq W$, where $n$ is `self`, $i$ is `index` and $W$ is the
252            /// width of the type.
253            ///
254            /// # Examples
255            /// See [here](super::bit_access#clear_bit).
256            #[inline]
257            fn clear_bit(&mut self, index: u64) {
258                clear_bit_signed(self, index)
259            }
260        }
261    };
262}
263apply_to_signeds!(impl_bit_access_signed);