malachite_base/num/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::num::basic::signeds::PrimitiveSigned;
10use crate::num::basic::unsigneds::PrimitiveUnsigned;
11use crate::num::conversion::traits::WrappingFrom;
12use crate::num::logic::traits::{BitConvertible, LeadingZeros};
13use alloc::vec::Vec;
14
15fn to_bits_asc_unsigned<T: PrimitiveUnsigned>(x: &T) -> Vec<bool> {
16    let mut bits = Vec::new();
17    let mut x = *x;
18    while x != T::ZERO {
19        bits.push(x.odd());
20        x >>= 1;
21    }
22    bits
23}
24
25fn to_bits_desc_unsigned<T: PrimitiveUnsigned>(x: &T) -> Vec<bool> {
26    let mut bits = Vec::new();
27    if *x == T::ZERO {
28        return bits;
29    }
30    bits.push(true);
31    if *x == T::ONE {
32        return bits;
33    }
34    let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(*x) - 2);
35    while mask != T::ZERO {
36        bits.push(*x & mask != T::ZERO);
37        mask >>= 1;
38    }
39    bits
40}
41
42fn from_bits_asc_unsigned<T: PrimitiveUnsigned, I: Iterator<Item = bool>>(bits: I) -> T {
43    let mut n = T::ZERO;
44    let mut mask = T::ONE;
45    for bit in bits {
46        if mask == T::ZERO {
47            assert!(!bit, "Bits cannot fit in integer of type {}", T::NAME);
48        } else {
49            if bit {
50                n |= mask;
51            }
52            mask <<= 1;
53        }
54    }
55    n
56}
57
58#[inline]
59fn from_bits_desc_unsigned<T: PrimitiveUnsigned, I: Iterator<Item = bool>>(bits: I) -> T {
60    let mut n = T::ZERO;
61    let high_mask = T::power_of_2(T::WIDTH - 1);
62    for bit in bits {
63        assert!(
64            n & high_mask == T::ZERO,
65            "Bits cannot fit in integer of type {}",
66            T::NAME
67        );
68        n <<= 1;
69        if bit {
70            n |= T::ONE;
71        }
72    }
73    n
74}
75
76macro_rules! impl_bit_convertible_unsigned {
77    ($t:ident) => {
78        impl BitConvertible for $t {
79            /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to
80            /// most-significant.
81            ///
82            /// If the number is 0, the [`Vec`] is empty; otherwise, it ends with `true`.
83            ///
84            /// # Worst-case complexity
85            /// $T(n) = O(n)$
86            ///
87            /// $M(n) = O(n)$
88            ///
89            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
90            ///
91            /// # Examples
92            /// See [here](super::bit_convertible#to_bits_asc).
93            #[inline]
94            fn to_bits_asc(&self) -> Vec<bool> {
95                to_bits_asc_unsigned(self)
96            }
97
98            /// Returns a [`Vec`] containing the bits of a number in descending order: most- to
99            /// least-significant.
100            ///
101            /// If the number is 0, the [`Vec`] is empty; otherwise, it begins with `true`.
102            ///
103            /// # Worst-case complexity
104            /// $T(n) = O(n)$
105            ///
106            /// $M(n) = O(n)$
107            ///
108            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
109            ///
110            /// # Examples
111            /// See [here](super::bit_convertible#to_bits_desc).
112            #[inline]
113            fn to_bits_desc(&self) -> Vec<bool> {
114                to_bits_desc_unsigned(self)
115            }
116
117            /// Converts an iterator of bits into a number. The bits should be in ascending order
118            /// (least- to most-significant).
119            ///
120            /// The function panics if the input represents a number that can't fit in the output
121            /// type.
122            ///
123            /// $$
124            /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\],
125            /// $$
126            /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
127            ///
128            /// # Worst-case complexity
129            /// $T(n) = O(n)$
130            ///
131            /// $M(n) = O(1)$
132            ///
133            /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`.
134            ///
135            /// # Panics
136            /// Panics if the bits represent a value that isn't representable by the output type.
137            ///
138            /// # Examples
139            /// See [here](super::bit_convertible#from_bits_asc).
140            #[inline]
141            fn from_bits_asc<I: Iterator<Item = bool>>(bits: I) -> $t {
142                from_bits_asc_unsigned(bits)
143            }
144
145            /// Converts an iterator of bits into a number. The bits should be in descending order
146            /// (most- to least-significant).
147            ///
148            /// The function panics if the input represents a number that can't fit in the output
149            /// type.
150            ///
151            /// $$
152            /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\],
153            /// $$
154            /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
155            ///
156            /// # Worst-case complexity
157            /// $T(n) = O(n)$
158            ///
159            /// $M(n) = O(1)$
160            ///
161            /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`.
162            ///
163            /// # Panics
164            /// Panics if the bits represent a value that isn't representable by the output type.
165            ///
166            /// # Examples
167            /// See [here](super::bit_convertible#from_bits_desc).
168            #[inline]
169            fn from_bits_desc<I: Iterator<Item = bool>>(bits: I) -> $t {
170                from_bits_desc_unsigned(bits)
171            }
172        }
173    };
174}
175apply_to_unsigneds!(impl_bit_convertible_unsigned);
176
177fn to_bits_asc_signed<T: PrimitiveSigned>(x: &T) -> Vec<bool> {
178    let mut bits = Vec::new();
179    let mut x = *x;
180    if x >= T::ZERO {
181        while x != T::ZERO {
182            bits.push(x.odd());
183            x >>= 1;
184        }
185        if !bits.is_empty() {
186            bits.push(false);
187        }
188    } else {
189        while x != T::NEGATIVE_ONE {
190            bits.push(x.odd());
191            x >>= 1;
192        }
193        bits.push(true);
194    }
195    bits
196}
197
198fn to_bits_desc_signed<T: PrimitiveSigned>(x: &T) -> Vec<bool> {
199    let mut bits = Vec::new();
200    if *x >= T::ZERO {
201        if *x == T::ZERO {
202            return bits;
203        }
204        bits.push(false);
205        bits.push(true);
206        if *x == T::ONE {
207            return bits;
208        }
209        let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(*x) - 2);
210        while mask != T::ZERO {
211            bits.push(*x & mask != T::ZERO);
212            mask >>= 1;
213        }
214    } else {
215        bits.push(true);
216        if *x == T::NEGATIVE_ONE {
217            return bits;
218        }
219        bits.push(false);
220        if *x == T::NEGATIVE_ONE << 1 {
221            return bits;
222        }
223        let mut mask = T::power_of_2(T::WIDTH - LeadingZeros::leading_zeros(!*x) - 2);
224        while mask != T::ZERO {
225            bits.push(*x & mask != T::ZERO);
226            mask >>= 1;
227        }
228    }
229    bits
230}
231
232fn from_bits_asc_signed<
233    U: PrimitiveUnsigned,
234    S: PrimitiveSigned + WrappingFrom<U>,
235    I: Iterator<Item = bool>,
236>(
237    bits: I,
238) -> S {
239    let mut n = U::ZERO;
240    let mut mask = U::ONE;
241    let mut last_bit = false;
242    for bit in bits {
243        if mask == U::ZERO {
244            assert_eq!(
245                bit,
246                last_bit,
247                "Bits cannot fit in integer of type {}",
248                S::NAME
249            );
250        } else {
251            if bit {
252                n |= mask;
253            }
254            mask <<= 1;
255            last_bit = bit;
256        }
257    }
258    if last_bit {
259        S::wrapping_from(n | mask.wrapping_neg())
260    } else {
261        S::wrapping_from(n)
262    }
263}
264
265#[inline]
266fn from_bits_desc_signed<
267    U: PrimitiveUnsigned,
268    S: PrimitiveSigned + WrappingFrom<U>,
269    I: Iterator<Item = bool>,
270>(
271    bits: I,
272) -> S {
273    let mut n = U::ZERO;
274    let high_mask = U::power_of_2(U::WIDTH - 2);
275    let mut first = true;
276    let mut sign_bit = false;
277    for bit in bits {
278        if first {
279            sign_bit = bit;
280            first = false;
281        } else {
282            assert!(
283                n & high_mask == U::ZERO,
284                "Bits cannot fit in integer of type {}",
285                S::NAME
286            );
287            n <<= 1;
288            if bit != sign_bit {
289                n |= U::ONE;
290            }
291        }
292    }
293    if sign_bit {
294        S::wrapping_from(!n)
295    } else {
296        S::wrapping_from(n)
297    }
298}
299
300macro_rules! impl_bit_convertible_signed {
301    ($u:ident, $s:ident) => {
302        impl BitConvertible for $s {
303            /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to
304            /// most-significant.
305            ///
306            /// If the number is 0, the [`Vec`] is empty; otherwise, the last bit is the sign bit:
307            /// `false` if the number is non-negative and `true` if it is negative.
308            ///
309            /// # Worst-case complexity
310            /// $T(n) = O(n)$
311            ///
312            /// $M(n) = O(n)$
313            ///
314            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
315            ///
316            /// # Examples
317            /// See [here](super::bit_convertible#to_bits_asc).
318            #[inline]
319            fn to_bits_asc(&self) -> Vec<bool> {
320                to_bits_asc_signed(self)
321            }
322
323            /// Returns a [`Vec`] containing the bits of a number in ascending order: most- to
324            /// least-significant.
325            ///
326            /// If the number is 0, the [`Vec`] is empty; otherwise, the first bit is the sign bit:
327            /// `false` if the number is non-negative and `true` if it is negative.
328            ///
329            /// # Worst-case complexity
330            /// $T(n) = O(n)$
331            ///
332            /// $M(n) = O(n)$
333            ///
334            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
335            ///
336            /// # Examples
337            /// See [here](super::bit_convertible#to_bits_desc).
338            #[inline]
339            fn to_bits_desc(&self) -> Vec<bool> {
340                to_bits_desc_signed(self)
341            }
342
343            /// Converts an iterator of bits into a value. The bits should be in ascending order
344            /// (least- to most-significant).
345            ///
346            /// The bits are interpreted as in twos-complement, and the last bit is the sign bit; if
347            /// it is `false`, the number is non-negative, and if it is `true`, the number is
348            /// negative.
349            ///
350            /// The function panics if the input represents a number that can't fit in the output
351            /// type.
352            ///
353            /// Let $k$ be `bits.count()`. If $k = 0$ or $b_{k-1}$ is `false`, then
354            /// $$
355            /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^i \[b_i\],
356            /// $$
357            /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
358            ///
359            /// If $b_{k-1}$ is `true`, then
360            /// $$
361            /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^i \[b_i\] \right ) - 2^k.
362            /// $$
363            ///
364            /// # Worst-case complexity
365            /// $T(n) = O(n)$
366            ///
367            /// $M(n) = O(1)$
368            ///
369            /// where $T$ is time, $M$ is additional memory, and $n$ is `bits.count()`.
370            ///
371            /// # Panics
372            /// Panics if the bits represent a value that doesn't fit in the output type.
373            ///
374            /// # Examples
375            /// See [here](super::bit_convertible#from_bits_asc).
376            #[inline]
377            fn from_bits_asc<I: Iterator<Item = bool>>(bits: I) -> $s {
378                from_bits_asc_signed::<$u, $s, _>(bits)
379            }
380
381            /// Converts an iterator of bits into a value. The bits should be in descending order
382            /// (most- to least-significant).
383            ///
384            /// The bits are interpreted as in twos-complement, and the first bit is the sign bit;
385            /// if it is `false`, the number is non-negative, and if it is `true`, the number is
386            /// negative.
387            ///
388            /// The function panics if the input represents a number that can't fit in the output
389            /// type.
390            ///
391            /// If `bits` is empty or $b_0$ is `false`, then
392            /// $$
393            /// f((b_i)_ {i=0}^{k-1}) = \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\],
394            /// $$
395            /// where braces denote the Iverson bracket, which converts a bit to 0 or 1.
396            ///
397            /// If $b_0$ is `true`, then
398            /// $$
399            /// f((b_i)_ {i=0}^{k-1}) = \left ( \sum_{i=0}^{k-1}2^{k-i-1} \[b_i\] \right ) - 2^k.
400            /// $$
401            ///
402            /// # Examples
403            /// See [here](super::bit_convertible#from_bits_desc).
404            #[inline]
405            fn from_bits_desc<I: Iterator<Item = bool>>(bits: I) -> $s {
406                from_bits_desc_signed::<$u, $s, _>(bits)
407            }
408        }
409    };
410}
411apply_to_unsigned_signed_pairs!(impl_bit_convertible_signed);