malachite_nz/integer/logic/
bit_convertible.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::integer::conversion::to_twos_complement_limbs::limbs_twos_complement_in_place;
11use crate::natural::Natural;
12use crate::natural::arithmetic::shr::limbs_slice_shr_in_place;
13use crate::platform::{Limb, SignedLimb};
14use alloc::vec::Vec;
15use itertools::Itertools;
16use malachite_base::num::basic::integers::PrimitiveInt;
17use malachite_base::num::basic::traits::Zero;
18use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
19use malachite_base::num::logic::traits::{BitConvertible, LowMask, NotAssign};
20
21// Given the bits of a non-negative `Integer`, in ascending order, checks whether the most
22// significant bit is `false`; if it isn't, appends an extra `false` bit. This way the `Integer`'s
23// non-negativity is preserved in its bits.
24//
25// # Worst-case complexity
26// Constant time and additional memory.
27pub_test! {bits_to_twos_complement_bits_non_negative(bits: &mut Vec<bool>) {
28    if !bits.is_empty() && *bits.last().unwrap() {
29        // Sign-extend with an extra false bit to indicate a positive Integer
30        bits.push(false);
31    }
32}}
33
34// Given the bits of the absolute value of a negative `Integer`, in ascending order, converts the
35// bits to two's complement. Returns whether there is a carry left over from the two's complement
36// conversion process.
37//
38// # Worst-case complexity
39// $T(n) = O(n)$
40//
41// $M(n) = O(1)$
42//
43// where $T$ is time, $M$ is additional memory, and $n$ is `bits.len()`.
44pub_test! {bits_slice_to_twos_complement_bits_negative(bits: &mut [bool]) -> bool {
45    let mut true_seen = false;
46    for bit in &mut *bits {
47        if true_seen {
48            bit.not_assign();
49        } else if *bit {
50            true_seen = true;
51        }
52    }
53    !true_seen
54}}
55
56// Given the bits of the absolute value of a negative `Integer`, in ascending order, converts the
57// bits to two's complement and checks whether the most significant bit is `true`; if it isn't,
58// appends an extra `true` bit. This way the `Integer`'s negativity is preserved in its bits. The
59// bits cannot be empty or contain only `false`s.
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 `bits.len()`.
67//
68// # Panics
69// Panics if `bits` contains only `false`s.
70pub_test! {bits_vec_to_twos_complement_bits_negative(bits: &mut Vec<bool>) {
71    assert!(!bits_slice_to_twos_complement_bits_negative(bits));
72    if bits.last() == Some(&false) {
73        // Sign-extend with an extra true bit to indicate a negative Integer
74        bits.push(true);
75    }
76}}
77
78fn from_bits_helper(mut limbs: Vec<Limb>, sign_bit: bool, last_width: u64) -> Integer {
79    if sign_bit {
80        if last_width != Limb::WIDTH {
81            *limbs.last_mut().unwrap() |= !Limb::low_mask(last_width);
82        }
83        assert!(!limbs_twos_complement_in_place(&mut limbs));
84    }
85    Integer::from_sign_and_abs(!sign_bit, Natural::from_owned_limbs_asc(limbs))
86}
87
88impl BitConvertible for Integer {
89    /// Returns a [`Vec`] containing the twos-complement bits of an [`Integer`] in ascending order:
90    /// least- to most-significant.
91    ///
92    /// The most significant bit indicates the sign; if the bit is `false`, the [`Integer`] is
93    /// positive, and if the bit is `true` it is negative. There are no trailing `false` bits if the
94    /// [`Integer`] is positive or trailing `true` bits if the [`Integer`] is negative, except as
95    /// necessary to include the correct sign bit. Zero is a special case: it contains no bits.
96    ///
97    /// This function is more efficient than [`to_bits_desc`](`Self::to_bits_desc`).
98    ///
99    /// # Worst-case complexity
100    /// $T(n) = O(n)$
101    ///
102    /// $M(n) = O(n)$
103    ///
104    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
105    ///
106    /// # Examples
107    /// ```
108    /// use malachite_base::num::basic::traits::Zero;
109    /// use malachite_base::num::logic::traits::BitConvertible;
110    /// use malachite_nz::integer::Integer;
111    ///
112    /// assert!(Integer::ZERO.to_bits_asc().is_empty());
113    /// // 105 = 01101001b, with a leading false bit to indicate sign
114    /// assert_eq!(
115    ///     Integer::from(105).to_bits_asc(),
116    ///     &[true, false, false, true, false, true, true, false]
117    /// );
118    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
119    /// assert_eq!(
120    ///     Integer::from(-105).to_bits_asc(),
121    ///     &[true, true, true, false, true, false, false, true]
122    /// );
123    /// ```
124    fn to_bits_asc(&self) -> Vec<bool> {
125        let mut bits = self.abs.to_bits_asc();
126        if self.sign {
127            bits_to_twos_complement_bits_non_negative(&mut bits);
128        } else {
129            bits_vec_to_twos_complement_bits_negative(&mut bits);
130        }
131        bits
132    }
133
134    /// Returns a [`Vec`] containing the twos-complement bits of an [`Integer`] in descending order:
135    /// most- to least-significant.
136    ///
137    /// The most significant bit indicates the sign; if the bit is `false`, the [`Integer`] is
138    /// positive, and if the bit is `true` it is negative. There are no leading `false` bits if the
139    /// [`Integer`] is positive or leading `true` bits if the [`Integer`] is negative, except as
140    /// necessary to include the correct sign bit. Zero is a special case: it contains no bits.
141    ///
142    /// This is similar to how `BigInteger`s in Java are represented.
143    ///
144    /// This function is less efficient than [`to_bits_asc`](`Self::to_bits_asc`).
145    ///
146    /// # Worst-case complexity
147    /// $T(n) = O(n)$
148    ///
149    /// $M(n) = O(n)$
150    ///
151    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
152    ///
153    /// # Examples
154    /// ```
155    /// use malachite_base::num::basic::traits::Zero;
156    /// use malachite_base::num::logic::traits::BitConvertible;
157    /// use malachite_nz::integer::Integer;
158    ///
159    /// assert!(Integer::ZERO.to_bits_desc().is_empty());
160    /// // 105 = 01101001b, with a leading false bit to indicate sign
161    /// assert_eq!(
162    ///     Integer::from(105).to_bits_desc(),
163    ///     &[false, true, true, false, true, false, false, true]
164    /// );
165    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
166    /// assert_eq!(
167    ///     Integer::from(-105).to_bits_desc(),
168    ///     &[true, false, false, true, false, true, true, true]
169    /// );
170    /// ```
171    fn to_bits_desc(&self) -> Vec<bool> {
172        let mut bits = self.to_bits_asc();
173        bits.reverse();
174        bits
175    }
176
177    /// Converts an iterator of twos-complement bits into an [`Integer`]. The bits should be in
178    /// ascending order (least- to most-significant).
179    ///
180    /// Let $k$ be `bits.count()`. If $k = 0$ or $b_{k-1}$ is `false`, then
181    /// $$
182    /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\],
183    /// $$
184    /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
185    ///
186    /// If $b_{k-1}$ is `true`, then
187    /// $$
188    /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^i \[b_i\] \right ) - 2^k.
189    /// $$
190    ///
191    /// # Worst-case complexity
192    /// $T(n) = O(n)$
193    ///
194    /// $M(n) = O(n)$
195    ///
196    /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`.
197    ///
198    /// # Examples
199    /// ```
200    /// use core::iter::empty;
201    /// use malachite_base::num::logic::traits::BitConvertible;
202    /// use malachite_nz::integer::Integer;
203    ///
204    /// assert_eq!(Integer::from_bits_asc(empty()), 0);
205    /// // 105 = 1101001b
206    /// assert_eq!(
207    ///     Integer::from_bits_asc(
208    ///         [true, false, false, true, false, true, true, false]
209    ///             .iter()
210    ///             .cloned()
211    ///     ),
212    ///     105
213    /// );
214    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
215    /// assert_eq!(
216    ///     Integer::from_bits_asc(
217    ///         [true, true, true, false, true, false, false, true]
218    ///             .iter()
219    ///             .cloned()
220    ///     ),
221    ///     -105
222    /// );
223    /// ```
224    fn from_bits_asc<I: Iterator<Item = bool>>(xs: I) -> Integer {
225        let mut limbs = Vec::new();
226        let mut last_width = 0;
227        let mut last_bit = false;
228        for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) {
229            let mut limb = 0;
230            let mut i = 0;
231            let mut mask = 1;
232            for bit in chunk {
233                if bit {
234                    limb |= mask;
235                }
236                mask <<= 1;
237                i += 1;
238                last_bit = bit;
239            }
240            last_width = i;
241            limbs.push(limb);
242        }
243        from_bits_helper(limbs, last_bit, last_width)
244    }
245
246    /// Converts an iterator of twos-complement bits into an [`Integer`]. The bits should be in
247    /// descending order (most- to least-significant).
248    ///
249    /// If `bits` is empty or $b_0$ is `false`, then
250    /// $$
251    /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\],
252    /// $$
253    /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
254    ///
255    /// If $b_0$ is `true`, then
256    /// $$
257    /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\] \right ) - 2^k.
258    /// $$
259    ///
260    /// # Worst-case complexity
261    /// $T(n) = O(n)$
262    ///
263    /// $M(n) = O(n)$
264    ///
265    /// where $T$ is time, $M$ is additional memory, and $n$ is `xs.count()`.
266    ///
267    /// # Examples
268    /// ```
269    /// use core::iter::empty;
270    /// use malachite_base::num::logic::traits::BitConvertible;
271    /// use malachite_nz::integer::Integer;
272    ///
273    /// assert_eq!(Integer::from_bits_desc(empty()), 0);
274    /// // 105 = 1101001b
275    /// assert_eq!(
276    ///     Integer::from_bits_desc(
277    ///         [false, true, true, false, true, false, false, true]
278    ///             .iter()
279    ///             .cloned()
280    ///     ),
281    ///     105
282    /// );
283    /// // -105 = 10010111 in two's complement, with a leading true bit to indicate sign
284    /// assert_eq!(
285    ///     Integer::from_bits_desc(
286    ///         [true, false, false, true, false, true, true, true]
287    ///             .iter()
288    ///             .cloned()
289    ///     ),
290    ///     -105
291    /// );
292    /// ```
293    fn from_bits_desc<I: Iterator<Item = bool>>(xs: I) -> Integer {
294        let mut limbs = Vec::new();
295        let mut last_width = 0;
296        let mut first_bit = false;
297        let mut first = true;
298        for chunk in &xs.chunks(usize::exact_from(Limb::WIDTH)) {
299            let mut limb = 0;
300            let mut i = 0;
301            for bit in chunk {
302                if first {
303                    first_bit = bit;
304                    first = false;
305                }
306                limb <<= 1;
307                if bit {
308                    limb |= 1;
309                }
310                i += 1;
311            }
312            last_width = i;
313            limbs.push(limb);
314        }
315        match limbs.len() {
316            0 => Integer::ZERO,
317            1 => {
318                if first_bit {
319                    if last_width != Limb::WIDTH {
320                        limbs[0] |= !Limb::low_mask(last_width);
321                    }
322                    Integer::from(SignedLimb::wrapping_from(limbs[0]))
323                } else {
324                    Integer::from(limbs[0])
325                }
326            }
327            _ => {
328                limbs.reverse();
329                if last_width != Limb::WIDTH {
330                    let smallest_limb = limbs[0];
331                    limbs[0] = 0;
332                    limbs_slice_shr_in_place(&mut limbs, Limb::WIDTH - last_width);
333                    limbs[0] |= smallest_limb;
334                }
335                from_bits_helper(limbs, first_bit, last_width)
336            }
337        }
338    }
339}