1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.

use alloc::vec::Vec;
use core::ops::Index;

/// Defines functions that access or modify individual bits in a number.
pub trait BitAccess {
    /// Determines whether a number has a `true` or `false` bit at `index`.
    fn get_bit(&self, index: u64) -> bool;

    /// Sets the bit at `index` to `true`.
    fn set_bit(&mut self, index: u64);

    /// Sets the bit at `index` to `false`.
    fn clear_bit(&mut self, index: u64);

    /// Sets the bit at `index` to whichever value `bit` is.
    ///
    /// # Worst-case complexity
    /// $T(n) = O(\max(T_S(n), T_C(n)))$,
    ///
    /// $M(n) = O(\max(M_S(n), M_C(n)))$
    ///
    /// where $T$ is time, $M$ is additional memory, $T_S$ and $M_S$ are the complexities of
    /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of
    /// [`clear_bit`](Self::clear_bit).
    ///
    /// # Panics
    /// See panics for [`set_bit`](Self::set_bit) and [`clear_bit`](Self::clear_bit).
    #[inline]
    fn assign_bit(&mut self, index: u64, bit: bool) {
        if bit {
            self.set_bit(index);
        } else {
            self.clear_bit(index);
        }
    }

    /// Sets the bit at `index` to the opposite of its original value.
    ///
    /// # Worst-case complexity
    /// $T(n) = O(T_G(n) + \max(T_S(n), T_C(n)))$,
    ///
    /// $M(n) = O(M_G(n) + \max(M_S(n), M_C(n)))$
    ///
    /// where $T$ is time, $M$ is additional memory, $T_G$ and $M_G$ are the complexities of
    /// [`get_bit`](Self::get_bit), $T_S$ and $M_S$ are the complexities of
    /// [`set_bit`](Self::set_bit), and $T_C$ and $M_C$ are the complexities of
    /// [`clear_bit`](Self::clear_bit).
    ///
    /// # Panics
    /// See panics for [`get_bit`](Self::get_bit), [`set_bit`](Self::set_bit) and
    /// [`clear_bit`](Self::clear_bit).
    #[inline]
    fn flip_bit(&mut self, index: u64) {
        if self.get_bit(index) {
            self.clear_bit(index);
        } else {
            self.set_bit(index);
        }
    }
}

/// Defines functions that access or modify blocks of adjacent bits in a number.
pub trait BitBlockAccess: Sized {
    type Bits;

    /// Extracts a block of bits whose first index is `start` and last index is `end - 1`.
    fn get_bits(&self, start: u64, end: u64) -> Self::Bits;

    /// Extracts a block of bits whose first index is `start` and last index is `end - 1`, taking
    /// ownership of `self`.
    ///
    /// # Worst-case complexity
    /// For the default implementation, same as [`get_bits`](Self::get_bits).
    ///
    /// # Panics
    /// For the default implementation, ee panics for [`get_bits`](Self::get_bits).
    ///
    /// # Examples
    /// ```
    /// use malachite_base::num::logic::traits::BitBlockAccess;
    ///
    /// assert_eq!((-0x5433i16).get_bits_owned(4, 8), 0xc);
    /// assert_eq!((-0x5433i16).get_bits_owned(5, 9), 14);
    /// assert_eq!((-0x5433i16).get_bits_owned(5, 5), 0);
    /// assert_eq!((-0x5433i16).get_bits_owned(100, 104), 0xf);
    /// ```
    #[inline]
    fn get_bits_owned(self, start: u64, end: u64) -> Self::Bits {
        self.get_bits(start, end)
    }

    /// Assigns the least-significant `end - start` bits of `bits` to bits `start` through `end - 1`
    /// (inclusive) of `self`.
    fn assign_bits(&mut self, start: u64, end: u64, bits: &Self::Bits);
}

/// Defines functions that express a number as a [`Vec`] of bits or construct a number from an
/// iterator of bits.
pub trait BitConvertible {
    /// Returns a [`Vec`] containing the bits of a number in ascending order: least- to
    /// most-significant.
    fn to_bits_asc(&self) -> Vec<bool>;

    /// Returns a [`Vec`] containing the bits of a number in descending order: most- to
    /// least-significant.
    fn to_bits_desc(&self) -> Vec<bool>;

    /// Converts an iterator of bits into a number. The input bits are in ascending order: least- to
    /// most-significant.
    fn from_bits_asc<I: Iterator<Item = bool>>(bits: I) -> Self;

    /// Converts an iterator of bits into a value. The input bits are in descending order: most- to
    /// least-significant.
    fn from_bits_desc<I: Iterator<Item = bool>>(bits: I) -> Self;
}

/// Defines an iterator over a value's bits.
pub trait BitIterable {
    type BitIterator: DoubleEndedIterator<Item = bool> + Index<u64>;

    /// Returns a double-ended iterator over a number's bits. When iterating in the forward
    /// direction, the iterator ends after the producing the number's most-significant bit.
    fn bits(self) -> Self::BitIterator;
}

/// Defines functions that search for the next `true` or `false` bit in a number, starting at a
/// specified index and searching in the more-significant direction.
pub trait BitScan {
    /// Given a number and a starting index, searches the number for the smallest index of a `false`
    /// bit that is greater than or equal to the starting index.
    fn index_of_next_false_bit(self, start: u64) -> Option<u64>;

    /// Given a number and a starting index, searches the number for the smallest index of a `true`
    /// bit that is greater than or equal to the starting index.
    fn index_of_next_true_bit(self, start: u64) -> Option<u64>;
}

/// Returns the number of ones in the binary representation of a number.
pub trait CountOnes {
    fn count_ones(self) -> u64;
}

/// Returns the number of zeros in the binary representation of a number.
pub trait CountZeros {
    fn count_zeros(self) -> u64;
}

/// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one
/// into the other.
pub trait HammingDistance<RHS = Self> {
    fn hamming_distance(self, other: RHS) -> u64;
}

/// Returns the Hamming distance between two numbers, or the number of bit flips needed to turn one
/// into the other.
///
/// This trait allows for the possibility of the distance being undefined for some pairs of numbers,
/// in which case [`checked_hamming_distance`](Self::checked_hamming_distance) should return `None`.
pub trait CheckedHammingDistance<RHS = Self> {
    fn checked_hamming_distance(self, other: RHS) -> Option<u64>;
}

/// Returns the number of leading zeros in the binary representation of a number.
pub trait LeadingZeros {
    fn leading_zeros(self) -> u64;
}

/// Returns a number whose least significant $b$ bits are `true` and whose other bits are `false`.
pub trait LowMask {
    fn low_mask(bits: u64) -> Self;
}

/// Replaces a number with its bitwise negation.
pub trait NotAssign {
    fn not_assign(&mut self);
}

// Returns the number of significant bits of a number.
pub trait SignificantBits {
    /// The number of bits it takes to represent `self`.
    fn significant_bits(self) -> u64;
}

/// Returns the number of trailing zeros in the binary representation of a number.
pub trait TrailingZeros {
    fn trailing_zeros(self) -> u64;
}