Skip to main content

malachite_nz/integer/logic/
bit_access.rs

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