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