malachite_base/num/logic/traits.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 alloc::vec::Vec;
10use core::ops::Index;
11
12/// Defines functions that access or modify individual bits in a number.
13pub trait BitAccess {
14 /// Determines whether a number has a `true` or `false` bit at `index`.
15 fn get_bit(&self, index: u64) -> bool;
16
17 /// Sets the bit at `index` to `true`.
18 fn set_bit(&mut self, index: u64);
19
20 /// Sets the bit at `index` to `false`.
21 fn clear_bit(&mut self, index: u64);
22
23 /// Sets the bit at `index` to whichever value `bit` is.
24 ///
25 /// # Worst-case complexity
26 /// $T(n) = O(\max(T_S(n), T_C(n)))$,
27 ///
28 /// $M(n) = O(\max(M_S(n), M_C(n)))$
29 ///
30 /// where $T$ is time, $M$ is additional memory, $T_S$ and $M_S$ are the complexities of
31 /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of
32 /// [`clear_bit`](Self::clear_bit).
33 ///
34 /// # Panics
35 /// See panics for [`set_bit`](Self::set_bit) and [`clear_bit`](Self::clear_bit).
36 #[inline]
37 fn assign_bit(&mut self, index: u64, bit: bool) {
38 if bit {
39 self.set_bit(index);
40 } else {
41 self.clear_bit(index);
42 }
43 }
44
45 /// Sets the bit at `index` to the opposite of its original value.
46 ///
47 /// # Worst-case complexity
48 /// $T(n) = O(T_G(n) + \max(T_S(n), T_C(n)))$,
49 ///
50 /// $M(n) = O(M_G(n) + \max(M_S(n), M_C(n)))$
51 ///
52 /// where $T$ is time, $M$ is additional memory, $T_G$ and $M_G$ are the complexities of
53 /// [`get_bit`](Self::get_bit), $T_S$ and $M_S$ are the complexities of
54 /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of
55 /// [`clear_bit`](Self::clear_bit).
56 ///
57 /// # Panics
58 /// See panics for [`get_bit`](Self::get_bit), [`set_bit`](Self::set_bit) and
59 /// [`clear_bit`](Self::clear_bit).
60 #[inline]
61 fn flip_bit(&mut self, index: u64) {
62 if self.get_bit(index) {
63 self.clear_bit(index);
64 } else {
65 self.set_bit(index);
66 }
67 }
68}
69
70/// Defines functions that access or modify blocks of adjacent bits in a number.
71pub trait BitBlockAccess: Sized {
72 type Bits;
73
74 /// Extracts a block of bits whose first index is `start` and last index is `end - 1`.
75 fn get_bits(&self, start: u64, end: u64) -> Self::Bits;
76
77 /// Extracts a block of bits whose first index is `start` and last index is `end - 1`, taking
78 /// ownership of `self`.
79 ///
80 /// # Worst-case complexity
81 /// For the default implementation, same as [`get_bits`](Self::get_bits).
82 ///
83 /// # Panics
84 /// For the default implementation, ee panics for [`get_bits`](Self::get_bits).
85 ///
86 /// # Examples
87 /// ```
88 /// use malachite_base::num::logic::traits::BitBlockAccess;
89 ///
90 /// assert_eq!((-0x5433i16).get_bits_owned(4, 8), 0xc);
91 /// assert_eq!((-0x5433i16).get_bits_owned(5, 9), 14);
92 /// assert_eq!((-0x5433i16).get_bits_owned(5, 5), 0);
93 /// assert_eq!((-0x5433i16).get_bits_owned(100, 104), 0xf);
94 /// ```
95 #[inline]
96 fn get_bits_owned(self, start: u64, end: u64) -> Self::Bits {
97 self.get_bits(start, end)
98 }
99
100 /// Assigns the least-significant `end - start` bits of `bits` to bits `start` through `end - 1`
101 /// (inclusive) of `self`.
102 fn assign_bits(&mut self, start: u64, end: u64, bits: &Self::Bits);
103}
104
105/// Defines functions that express a number as a [`Vec`] of bits or construct a number from an
106/// iterator of bits.
107pub trait BitConvertible {
108 /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to
109 /// most-significant.
110 fn to_bits_asc(&self) -> Vec<bool>;
111
112 /// Returns a [`Vec`] containing the bits of a number in descending order: most- to
113 /// least-significant.
114 fn to_bits_desc(&self) -> Vec<bool>;
115
116 /// Converts an iterator of bits into a number. The input bits are in ascending order: least- to
117 /// most-significant.
118 fn from_bits_asc<I: Iterator<Item = bool>>(bits: I) -> Self;
119
120 /// Converts an iterator of bits into a value. The input bits are in descending order: most- to
121 /// least-significant.
122 fn from_bits_desc<I: Iterator<Item = bool>>(bits: I) -> Self;
123}
124
125/// Defines an iterator over a value's bits.
126pub trait BitIterable {
127 type BitIterator: DoubleEndedIterator<Item = bool> + Index<u64>;
128
129 /// Returns a double-ended iterator over a number's bits. When iterating in the forward
130 /// direction, the iterator ends after the producing the number's most-significant bit.
131 fn bits(self) -> Self::BitIterator;
132}
133
134/// Defines functions that search for the next `true` or `false` bit in a number, starting at a
135/// specified index and searching in the more-significant direction.
136pub trait BitScan {
137 /// Given a number and a starting index, searches the number for the smallest index of a `false`
138 /// bit that is greater than or equal to the starting index.
139 fn index_of_next_false_bit(self, start: u64) -> Option<u64>;
140
141 /// Given a number and a starting index, searches the number for the smallest index of a `true`
142 /// bit that is greater than or equal to the starting index.
143 fn index_of_next_true_bit(self, start: u64) -> Option<u64>;
144}
145
146/// Returns the number of ones in the binary representation of a number.
147pub trait CountOnes {
148 fn count_ones(self) -> u64;
149}
150
151/// Returns the number of zeros in the binary representation of a number.
152pub trait CountZeros {
153 fn count_zeros(self) -> u64;
154}
155
156/// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one
157/// into the other.
158pub trait HammingDistance<RHS = Self> {
159 fn hamming_distance(self, other: RHS) -> u64;
160}
161
162/// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one
163/// into the other.
164///
165/// This trait allows for the possibility of the distance being undefined for some pairs of numbers,
166/// in which case [`checked_hamming_distance`](Self::checked_hamming_distance) should return `None`.
167pub trait CheckedHammingDistance<RHS = Self> {
168 fn checked_hamming_distance(self, other: RHS) -> Option<u64>;
169}
170
171/// Returns the number of leading zeros in the binary representation of a number.
172pub trait LeadingZeros {
173 fn leading_zeros(self) -> u64;
174}
175
176/// Returns a number whose least significant $b$ bits are `true` and whose other bits are `false`.
177pub trait LowMask {
178 fn low_mask(bits: u64) -> Self;
179}
180
181/// Replaces a number with its bitwise negation.
182pub trait NotAssign {
183 fn not_assign(&mut self);
184}
185
186// Returns the number of significant bits of a number.
187pub trait SignificantBits {
188 /// The number of bits it takes to represent `self`.
189 fn significant_bits(self) -> u64;
190}
191
192/// Returns the number of trailing zeros in the binary representation of a number.
193pub trait TrailingZeros {
194 fn trailing_zeros(self) -> u64;
195}