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}