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