malachite_nz/integer/logic/
bit_iterable.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::integer::Integer;
10use crate::natural::Natural;
11use crate::natural::logic::bit_iterable::NaturalBitIterator;
12use core::ops::Index;
13use malachite_base::num::logic::traits::{BitAccess, BitIterable};
14
15/// A double-ended iterator over the two's complement bits of the negative of an [`Integer`].
16///
17/// The forward order is ascending (least-significant first). There may be at most one implicit
18/// most-significant `true` bit.
19#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
20pub struct NegativeBitIterator<'a> {
21    pub(crate) bits: NaturalBitIterator<'a>,
22    i: u64,
23    j: u64,
24    first_true_index: Option<u64>,
25}
26
27impl Iterator for NegativeBitIterator<'_> {
28    type Item = bool;
29
30    fn next(&mut self) -> Option<bool> {
31        let previous_i = self.i;
32        self.bits.next().map(|bit| {
33            self.i += 1;
34            if let Some(first_true_index) = self.first_true_index {
35                if previous_i <= first_true_index {
36                    bit
37                } else {
38                    !bit
39                }
40            } else {
41                if bit {
42                    self.first_true_index = Some(previous_i);
43                }
44                bit
45            }
46        })
47    }
48
49    #[inline]
50    fn size_hint(&self) -> (usize, Option<usize>) {
51        self.bits.size_hint()
52    }
53}
54
55impl DoubleEndedIterator for NegativeBitIterator<'_> {
56    fn next_back(&mut self) -> Option<bool> {
57        let previous_j = self.j;
58        self.bits.next_back().map(|bit| {
59            if self.j != 0 {
60                self.j -= 1;
61            }
62            if self.first_true_index.is_none() {
63                let mut i = 0;
64                while !self.bits[i] {
65                    i += 1;
66                }
67                self.first_true_index = Some(i);
68            }
69            let first_true_index = self.first_true_index.unwrap();
70            if previous_j <= first_true_index {
71                bit
72            } else {
73                !bit
74            }
75        })
76    }
77}
78
79impl ExactSizeIterator for NegativeBitIterator<'_> {}
80
81trait SignExtendedBitIterator: DoubleEndedIterator<Item = bool> {
82    const EXTENSION: bool;
83
84    fn needs_sign_extension(&self) -> bool;
85
86    fn iterate_forward(&mut self, extension_checked: &mut bool) -> Option<bool> {
87        let next = self.next();
88        if next.is_none() {
89            if *extension_checked {
90                None
91            } else {
92                *extension_checked = true;
93                if self.needs_sign_extension() {
94                    Some(Self::EXTENSION)
95                } else {
96                    None
97                }
98            }
99        } else {
100            next
101        }
102    }
103
104    fn iterate_backward(&mut self, extension_checked: &mut bool) -> Option<bool> {
105        if !*extension_checked {
106            *extension_checked = true;
107            if self.needs_sign_extension() {
108                return Some(Self::EXTENSION);
109            }
110        }
111        self.next_back()
112    }
113}
114
115impl SignExtendedBitIterator for NaturalBitIterator<'_> {
116    const EXTENSION: bool = false;
117
118    fn needs_sign_extension(&self) -> bool {
119        self[self.significant_bits - 1]
120    }
121}
122
123impl SignExtendedBitIterator for NegativeBitIterator<'_> {
124    const EXTENSION: bool = true;
125
126    fn needs_sign_extension(&self) -> bool {
127        let mut i = 0;
128        while !self.bits[i] {
129            i += 1;
130        }
131        let last_bit_index = self.bits.significant_bits - 1;
132        if i == last_bit_index {
133            !self.bits[last_bit_index]
134        } else {
135            self.bits[last_bit_index]
136        }
137    }
138}
139
140/// A double-ended iterator over the twos-complement bits of an [`Integer`].
141///
142/// The forward order is ascending (least-significant first). The most significant bit corresponds
143/// to the sign of the [`Integer`]; `false` for non-negative and `true` for negative. This means
144/// that there may be a single most-significant sign-extension bit.
145///
146/// This `struct` is created by [`BitIterable::bits`]; see its documentation for more.
147#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
148pub enum IntegerBitIterator<'a> {
149    Zero,
150    Positive(NaturalBitIterator<'a>, bool),
151    Negative(NegativeBitIterator<'a>, bool),
152}
153
154impl Iterator for IntegerBitIterator<'_> {
155    type Item = bool;
156
157    fn next(&mut self) -> Option<bool> {
158        match self {
159            IntegerBitIterator::Zero => None,
160            IntegerBitIterator::Positive(bits, extension_checked) => {
161                bits.iterate_forward(extension_checked)
162            }
163            IntegerBitIterator::Negative(bits, extension_checked) => {
164                bits.iterate_forward(extension_checked)
165            }
166        }
167    }
168}
169
170impl DoubleEndedIterator for IntegerBitIterator<'_> {
171    fn next_back(&mut self) -> Option<bool> {
172        match self {
173            IntegerBitIterator::Zero => None,
174            IntegerBitIterator::Positive(bits, extension_checked) => {
175                bits.iterate_backward(extension_checked)
176            }
177            IntegerBitIterator::Negative(bits, extension_checked) => {
178                bits.iterate_backward(extension_checked)
179            }
180        }
181    }
182}
183
184impl Index<u64> for IntegerBitIterator<'_> {
185    type Output = bool;
186
187    /// A function to retrieve an [`Integer`]'s two's complement bits by index. Indexing at or above
188    /// the significant bit count returns `false` or `true` bits, depending on the [`Integer`]'s
189    /// sign.
190    ///
191    /// This is equivalent to [`get_bit`](malachite_base::num::logic::traits::BitAccess::get_bit).
192    ///
193    /// # Examples
194    /// ```
195    /// use malachite_base::num::basic::traits::Zero;
196    /// use malachite_base::num::logic::traits::BitIterable;
197    /// use malachite_nz::integer::Integer;
198    ///
199    /// assert_eq!(Integer::ZERO.bits()[0], false);
200    ///
201    /// // -105 = 10010111 in two's complement
202    /// let n = Integer::from(-105);
203    /// let bits = n.bits();
204    /// assert_eq!(bits[0], true);
205    /// assert_eq!(bits[1], true);
206    /// assert_eq!(bits[2], true);
207    /// assert_eq!(bits[3], false);
208    /// assert_eq!(bits[4], true);
209    /// assert_eq!(bits[5], false);
210    /// assert_eq!(bits[6], false);
211    /// assert_eq!(bits[7], true);
212    /// assert_eq!(bits[100], true);
213    /// ```
214    fn index(&self, index: u64) -> &bool {
215        let bit = match self {
216            IntegerBitIterator::Zero => false,
217            IntegerBitIterator::Positive(bits, _) => bits.limbs.n.get_bit(index),
218            IntegerBitIterator::Negative(bits, _) => bits.bits.limbs.n.get_bit_neg(index),
219        };
220        if bit { &true } else { &false }
221    }
222}
223
224impl Natural {
225    // Returns a double-ended iterator over the two's complement bits of the negative of a
226    // `Natural`. The forward order is ascending, so that less significant bits appear first. There
227    // may be at most one trailing `true` bit going forward, or leading `true` bit going backward.
228    // The `Natural` cannot be zero.
229    //
230    // # Worst-case complexity
231    // Constant time and additional memory.
232    fn negative_bits(&self) -> NegativeBitIterator<'_> {
233        assert_ne!(*self, 0, "Cannot get negative bits of 0.");
234        let bits = self.bits();
235        NegativeBitIterator {
236            bits,
237            first_true_index: None,
238            i: 0,
239            j: bits.significant_bits - 1,
240        }
241    }
242}
243
244impl<'a> BitIterable for &'a Integer {
245    type BitIterator = IntegerBitIterator<'a>;
246
247    /// Returns a double-ended iterator over the bits of an [`Integer`].
248    ///
249    /// The forward order is ascending, so that less significant bits appear first. There are no
250    /// trailing false bits going forward, or leading falses going backward, except for possibly a
251    /// most-significant sign-extension bit.
252    ///
253    /// If it's necessary to get a [`Vec`] of all the bits, consider using
254    /// [`to_bits_asc`](malachite_base::num::logic::traits::BitConvertible::to_bits_asc) or
255    /// [`to_bits_desc`](malachite_base::num::logic::traits::BitConvertible::to_bits_desc) instead.
256    ///
257    /// # Worst-case complexity
258    /// Constant time and additional memory.
259    ///
260    /// # Examples
261    /// ```
262    /// use itertools::Itertools;
263    /// use malachite_base::num::basic::traits::Zero;
264    /// use malachite_base::num::logic::traits::BitIterable;
265    /// use malachite_nz::integer::Integer;
266    ///
267    /// assert_eq!(Integer::ZERO.bits().next(), None);
268    /// // 105 = 01101001b, with a leading false bit to indicate sign
269    /// assert_eq!(
270    ///     Integer::from(105).bits().collect_vec(),
271    ///     &[true, false, false, true, false, true, true, false]
272    /// );
273    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
274    /// assert_eq!(
275    ///     Integer::from(-105).bits().collect_vec(),
276    ///     &[true, true, true, false, true, false, false, true]
277    /// );
278    ///
279    /// assert_eq!(Integer::ZERO.bits().next_back(), None);
280    /// // 105 = 01101001b, with a leading false bit to indicate sign
281    /// assert_eq!(
282    ///     Integer::from(105).bits().rev().collect_vec(),
283    ///     &[false, true, true, false, true, false, false, true]
284    /// );
285    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
286    /// assert_eq!(
287    ///     Integer::from(-105).bits().rev().collect_vec(),
288    ///     &[true, false, false, true, false, true, true, true]
289    /// );
290    /// ```
291    fn bits(self) -> IntegerBitIterator<'a> {
292        if *self == 0 {
293            IntegerBitIterator::Zero
294        } else if self.sign {
295            IntegerBitIterator::Positive(self.abs.bits(), false)
296        } else {
297            IntegerBitIterator::Negative(self.abs.negative_bits(), false)
298        }
299    }
300}