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}