malachite_nz/integer/logic/bit_access.rs
1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5// Copyright © 1991, 1993-1995, 1997, 1999, 2000, 2001, 2002, 2012 Free Software Foundation,
6// Inc.
7//
8// This file is part of Malachite.
9//
10// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
11// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
12// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
13
14use crate::integer::Integer;
15use crate::natural::InnerNatural::{Large, Small};
16use crate::natural::arithmetic::add::limbs_slice_add_limb_in_place;
17use crate::natural::arithmetic::sub::limbs_sub_limb_in_place;
18use crate::natural::{Natural, bit_to_limb_count_floor};
19use crate::platform::Limb;
20use alloc::vec::Vec;
21use core::cmp::Ordering::*;
22use malachite_base::num::arithmetic::traits::{PowerOf2, WrappingAddAssign, WrappingNegAssign};
23use malachite_base::num::basic::integers::PrimitiveInt;
24use malachite_base::num::logic::traits::BitAccess;
25use malachite_base::slices::{slice_leading_zeros, slice_test_zero};
26
27// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an
28// action equivalent to taking the two's complement of the limbs and getting the bit at the
29// specified index. Sufficiently high indices will return `true`. The slice cannot be empty or
30// contain only zeros.
31//
32// # Worst-case complexity
33// $T(n) = O(n)$
34//
35// $M(n) = O(1)$
36//
37// where $T$ is time, $M$ is additional memory, and $n$ is `xs.len()`.
38//
39// This is equivalent to `mpz_tstbit` from `mpz/tstbit.c`, GMP 6.2.1, where `d` is negative.
40pub_test! {limbs_get_bit_neg(xs: &[Limb], index: u64) -> bool {
41 let x_i = bit_to_limb_count_floor(index);
42 if x_i >= xs.len() {
43 // We're indexing into the infinite suffix of 1s
44 true
45 } else {
46 let x = if slice_test_zero(&xs[..x_i]) {
47 xs[x_i].wrapping_neg()
48 } else {
49 !xs[x_i]
50 };
51 x.get_bit(index & Limb::WIDTH_MASK)
52 }
53}}
54
55// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an
56// action equivalent to taking the two's complement of the limbs, setting a bit at the specified
57// index to `true`, and taking the two's complement again. Indices that are outside the bounds of
58// the slice will result in no action being taken, since negative numbers in two's complement have
59// infinitely many leading 1s. The slice cannot be empty or contain only zeros.
60//
61// # Worst-case complexity
62// $T(n) = O(n)$
63//
64// $M(n) = O(1)$
65//
66// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
67//
68// # Panics
69// If the slice contains only zeros a panic may occur.
70//
71// This is equivalent to `mpz_setbit` from `mpz/setbit.c`, GMP 6.2.1, where `d` is negative.
72pub_test! {limbs_set_bit_neg(xs: &mut [Limb], index: u64) {
73 let x_i = bit_to_limb_count_floor(index);
74 if x_i >= xs.len() {
75 return;
76 }
77 let reduced_index = index & Limb::WIDTH_MASK;
78 let zero_bound = slice_leading_zeros(xs);
79 match x_i.cmp(&zero_bound) {
80 Equal => {
81 let boundary = &mut xs[x_i];
82 // boundary != 0 here
83 *boundary -= 1;
84 boundary.clear_bit(reduced_index);
85 // boundary != Limb::MAX here
86 *boundary += 1;
87 }
88 Less => {
89 assert!(!limbs_sub_limb_in_place(
90 &mut xs[x_i..],
91 Limb::power_of_2(reduced_index),
92 ));
93 }
94 Greater => {
95 xs[x_i].clear_bit(reduced_index);
96 }
97 }
98}}
99
100fn limbs_clear_bit_neg_helper(xs: &mut [Limb], x_i: usize, reduced_index: u64) -> bool {
101 let zero_bound = slice_leading_zeros(xs);
102 match x_i.cmp(&zero_bound) {
103 Equal => {
104 // xs[x_i] != 0 here
105 let mut boundary = xs[x_i] - 1;
106 boundary.set_bit(reduced_index);
107 boundary.wrapping_add_assign(1);
108 xs[x_i] = boundary;
109 boundary == 0 && limbs_slice_add_limb_in_place(&mut xs[x_i + 1..], 1)
110 }
111 Greater => {
112 xs[x_i].set_bit(reduced_index);
113 false
114 }
115 _ => false,
116 }
117}
118
119// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an
120// action equivalent to taking the two's complement of the limbs, setting a bit at the specified
121// index to `false`, and taking the two's complement again. Inputs that would result in new `true`
122// bits outside of the slice will cause a panic. The slice cannot be empty or contain only zeros.
123//
124// # Worst-case complexity
125// $T(n) = O(n)$
126//
127// $M(n) = O(1)$
128//
129// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
130//
131// # Panics
132// Panics if evaluation would require new `true` bits outside of the slice. If the slice contains
133// only zeros a panic may occur.
134//
135// This is equivalent to `mpz_clrbit` from `mpz/clrbit.c`, GMP 6.2.1, where `d` is negative and
136// `bit_idx` small enough that no additional memory needs to be given to `d`.
137pub fn limbs_slice_clear_bit_neg(xs: &mut [Limb], index: u64) {
138 let x_i = bit_to_limb_count_floor(index);
139 let reduced_index = index & Limb::WIDTH_MASK;
140 assert!(
141 x_i < xs.len() && !limbs_clear_bit_neg_helper(xs, x_i, reduced_index),
142 "Setting bit cannot be done within existing slice"
143 );
144}
145
146// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, performs an
147// action equivalent to taking the two's complement of the limbs, setting a bit at the specified
148// index to `false`, and taking the two's complement again. Sufficiently high indices will increase
149// the length of the limbs vector. The slice cannot be empty or contain only zeros.
150//
151// # Worst-case complexity
152// $T(n) = O(n)$
153//
154// $M(n) = O(n)$
155//
156// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
157//
158// # Panics
159// If the slice contains only zeros a panic may occur.
160//
161// This is equivalent to `mpz_clrbit` from `mpz/clrbit.c`, GMP 6.2.1, where `d` is negative.
162pub_test! {limbs_vec_clear_bit_neg(xs: &mut Vec<Limb>, index: u64) {
163 let x_i = bit_to_limb_count_floor(index);
164 let reduced_index = index & Limb::WIDTH_MASK;
165 if x_i < xs.len() {
166 if limbs_clear_bit_neg_helper(xs, x_i, reduced_index) {
167 xs.push(1);
168 }
169 } else {
170 xs.resize(x_i, 0);
171 xs.push(Limb::power_of_2(reduced_index));
172 }
173}}
174
175impl Natural {
176 // self cannot be zero
177 pub(crate) fn get_bit_neg(&self, index: u64) -> bool {
178 match self {
179 Self(Small(small)) => index >= Limb::WIDTH || small.wrapping_neg().get_bit(index),
180 Self(Large(limbs)) => limbs_get_bit_neg(limbs, index),
181 }
182 }
183
184 // self cannot be zero
185 fn set_bit_neg(&mut self, index: u64) {
186 match self {
187 Self(Small(small)) => {
188 if index < Limb::WIDTH {
189 small.wrapping_neg_assign();
190 small.set_bit(index);
191 small.wrapping_neg_assign();
192 }
193 }
194 Self(Large(limbs)) => {
195 limbs_set_bit_neg(limbs, index);
196 self.trim();
197 }
198 }
199 }
200
201 // self cannot be zero
202 fn clear_bit_neg(&mut self, index: u64) {
203 match self {
204 Self(Small(small)) if index < Limb::WIDTH => {
205 let mut cleared_small = small.wrapping_neg();
206 cleared_small.clear_bit(index);
207 if cleared_small == 0 {
208 *self = Self(Large(vec![0, 1]));
209 } else {
210 *small = cleared_small.wrapping_neg();
211 }
212 }
213 Self(Small(_)) => {
214 let limbs = self.promote_in_place();
215 limbs_vec_clear_bit_neg(limbs, index);
216 }
217 Self(Large(limbs)) => {
218 limbs_vec_clear_bit_neg(limbs, index);
219 }
220 }
221 }
222}
223
224/// Provides functions for accessing and modifying the $i$th bit of a [`Integer`], or the
225/// coefficient of $2^i$ in its two's complement binary expansion.
226///
227/// # Examples
228/// ```
229/// use malachite_base::num::basic::traits::{NegativeOne, Zero};
230/// use malachite_base::num::logic::traits::BitAccess;
231/// use malachite_nz::integer::Integer;
232///
233/// let mut x = Integer::ZERO;
234/// x.assign_bit(2, true);
235/// x.assign_bit(5, true);
236/// x.assign_bit(6, true);
237/// assert_eq!(x, 100);
238/// x.assign_bit(2, false);
239/// x.assign_bit(5, false);
240/// x.assign_bit(6, false);
241/// assert_eq!(x, 0);
242///
243/// let mut x = Integer::from(-0x100);
244/// x.assign_bit(2, true);
245/// x.assign_bit(5, true);
246/// x.assign_bit(6, true);
247/// assert_eq!(x, -156);
248/// x.assign_bit(2, false);
249/// x.assign_bit(5, false);
250/// x.assign_bit(6, false);
251/// assert_eq!(x, -256);
252///
253/// let mut x = Integer::ZERO;
254/// x.flip_bit(10);
255/// assert_eq!(x, 1024);
256/// x.flip_bit(10);
257/// assert_eq!(x, 0);
258///
259/// let mut x = Integer::NEGATIVE_ONE;
260/// x.flip_bit(10);
261/// assert_eq!(x, -1025);
262/// x.flip_bit(10);
263/// assert_eq!(x, -1);
264/// ```
265impl BitAccess for Integer {
266 /// Determines whether the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its two's
267 /// complement binary expansion, is 0 or 1.
268 ///
269 /// `false` means 0 and `true` means 1. Getting bits beyond the [`Integer`]'s width is allowed;
270 /// those bits are `false` if the [`Integer`] is non-negative and `true` if it is negative.
271 ///
272 /// If $n \geq 0$, let
273 /// $$
274 /// n = \sum_{i=0}^\infty 2^{b_i};
275 /// $$
276 /// but if $n < 0$, let
277 /// $$
278 /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i},
279 /// $$
280 /// where for all $i$, $b_i\in \\{0, 1\\}$.
281 ///
282 /// $f(n, i) = (b_i = 1)$.
283 ///
284 /// # Worst-case complexity
285 /// $T(n) = O(n)$
286 ///
287 /// $M(n) = O(1)$
288 ///
289 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
290 ///
291 /// # Examples
292 /// ```
293 /// use malachite_base::num::arithmetic::traits::Pow;
294 /// use malachite_base::num::logic::traits::BitAccess;
295 /// use malachite_nz::integer::Integer;
296 ///
297 /// assert_eq!(Integer::from(123).get_bit(2), false);
298 /// assert_eq!(Integer::from(123).get_bit(3), true);
299 /// assert_eq!(Integer::from(123).get_bit(100), false);
300 /// assert_eq!(Integer::from(-123).get_bit(0), true);
301 /// assert_eq!(Integer::from(-123).get_bit(1), false);
302 /// assert_eq!(Integer::from(-123).get_bit(100), true);
303 /// assert_eq!(Integer::from(10u32).pow(12).get_bit(12), true);
304 /// assert_eq!(Integer::from(10u32).pow(12).get_bit(100), false);
305 /// assert_eq!((-Integer::from(10u32).pow(12)).get_bit(12), true);
306 /// assert_eq!((-Integer::from(10u32).pow(12)).get_bit(100), true);
307 /// ```
308 fn get_bit(&self, index: u64) -> bool {
309 match self {
310 Self { sign: true, abs } => abs.get_bit(index),
311 Self { sign: false, abs } => abs.get_bit_neg(index),
312 }
313 }
314
315 /// Sets the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its two's complement
316 /// binary expansion, to 1.
317 ///
318 /// If $n \geq 0$, let
319 /// $$
320 /// n = \sum_{i=0}^\infty 2^{b_i};
321 /// $$
322 /// but if $n < 0$, let
323 /// $$
324 /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i},
325 /// $$
326 /// where for all $i$, $b_i\in \\{0, 1\\}$.
327 /// $$
328 /// n \gets \\begin{cases}
329 /// n + 2^j & \text{if} \\quad b_j = 0, \\\\
330 /// n & \text{otherwise}.
331 /// \\end{cases}
332 /// $$
333 ///
334 /// # Worst-case complexity
335 /// $T(n) = O(n)$
336 ///
337 /// $M(n) = O(n)$
338 ///
339 /// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
340 ///
341 /// # Examples
342 /// ```
343 /// use malachite_base::num::basic::traits::Zero;
344 /// use malachite_base::num::logic::traits::BitAccess;
345 /// use malachite_nz::integer::Integer;
346 ///
347 /// let mut x = Integer::ZERO;
348 /// x.set_bit(2);
349 /// x.set_bit(5);
350 /// x.set_bit(6);
351 /// assert_eq!(x, 100);
352 ///
353 /// let mut x = Integer::from(-0x100);
354 /// x.set_bit(2);
355 /// x.set_bit(5);
356 /// x.set_bit(6);
357 /// assert_eq!(x, -156);
358 /// ```
359 fn set_bit(&mut self, index: u64) {
360 match self {
361 Self { sign: true, abs } => abs.set_bit(index),
362 Self { sign: false, abs } => abs.set_bit_neg(index),
363 }
364 }
365
366 /// Sets the $i$th bit of an [`Integer`], or the coefficient of $2^i$ in its binary expansion,
367 /// to 0.
368 ///
369 /// If $n \geq 0$, let
370 /// $$
371 /// n = \sum_{i=0}^\infty 2^{b_i};
372 /// $$
373 /// but if $n < 0$, let
374 /// $$
375 /// -n - 1 = \sum_{i=0}^\infty 2^{1 - b_i},
376 /// $$
377 /// where for all $i$, $b_i\in \\{0, 1\\}$.
378 /// $$
379 /// n \gets \\begin{cases}
380 /// n - 2^j & \text{if} \\quad b_j = 1, \\\\
381 /// n & \text{otherwise}.
382 /// \\end{cases}
383 /// $$
384 ///
385 /// # Worst-case complexity
386 /// $T(n) = O(n)$
387 ///
388 /// $M(n) = O(n)$
389 ///
390 /// where $T$ is time, $M$ is additional memory, and $n$ is `index`.
391 ///
392 /// # Examples
393 /// ```
394 /// use malachite_base::num::logic::traits::BitAccess;
395 /// use malachite_nz::integer::Integer;
396 ///
397 /// let mut x = Integer::from(0x7f);
398 /// x.clear_bit(0);
399 /// x.clear_bit(1);
400 /// x.clear_bit(3);
401 /// x.clear_bit(4);
402 /// assert_eq!(x, 100);
403 ///
404 /// let mut x = Integer::from(-156);
405 /// x.clear_bit(2);
406 /// x.clear_bit(5);
407 /// x.clear_bit(6);
408 /// assert_eq!(x, -256);
409 /// ```
410 fn clear_bit(&mut self, index: u64) {
411 match self {
412 Self { sign: true, abs } => abs.clear_bit(index),
413 Self { sign: false, abs } => abs.clear_bit_neg(index),
414 }
415 }
416}