blob: 0fb1a6aca2b08e10f06a39807fb93382f7594060 [file] [log] [blame]
Jeff Brown66db6892010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef UTILS_BITSET_H
18#define UTILS_BITSET_H
19
20#include <stdint.h>
Jeff Brown9a0a76d2012-03-16 14:45:49 -070021#include <utils/TypeHelpers.h>
Jeff Brown66db6892010-04-22 18:58:52 -070022
23/*
Michael Wrightf32317c2020-07-12 00:38:19 +010024 * A class to provide efficient manipulation of bitsets.
Steven Morelandb8f152d2017-12-18 16:14:13 -080025 *
Michael Wrightf32317c2020-07-12 00:38:19 +010026 * Consider using std::bitset<32> or std::bitset<64> if all you want is a class to do basic bit
27 * manipulation (i.e. AND / OR / XOR / flip / etc). These classes are only needed if you want to
28 * efficiently perform operations like finding the first set bit in a bitset and you want to
29 * avoid using the built-in functions (e.g. __builtin_clz) on std::bitset::to_ulong.
Jeff Brown66db6892010-04-22 18:58:52 -070030 */
31
32namespace android {
33
34// A simple set of 32 bits that can be individually marked or cleared.
35struct BitSet32 {
36 uint32_t value;
37
Michael Wright2ec06452014-03-19 11:23:01 -070038 inline BitSet32() : value(0UL) { }
Jeff Brown66db6892010-04-22 18:58:52 -070039 explicit inline BitSet32(uint32_t value) : value(value) { }
40
41 // Gets the value associated with a particular bit index.
Michael Wright2ec06452014-03-19 11:23:01 -070042 static inline uint32_t valueForBit(uint32_t n) { return 0x80000000UL >> n; }
Jeff Brown66db6892010-04-22 18:58:52 -070043
44 // Clears the bit set.
Michael Wright2ec06452014-03-19 11:23:01 -070045 inline void clear() { clear(value); }
46
47 static inline void clear(uint32_t& value) { value = 0UL; }
Jeff Brown66db6892010-04-22 18:58:52 -070048
Jeff Brown7d90df82010-09-26 22:20:12 -070049 // Returns the number of marked bits in the set.
Michael Wright2ec06452014-03-19 11:23:01 -070050 inline uint32_t count() const { return count(value); }
51
Michael Wright23e13632020-07-12 00:07:14 +010052 static inline uint32_t count(uint32_t value) {
53 return static_cast<uint32_t>(__builtin_popcountl(value));
54 }
Jeff Brown7d90df82010-09-26 22:20:12 -070055
Jeff Brown66db6892010-04-22 18:58:52 -070056 // Returns true if the bit set does not contain any marked bits.
Michael Wright2ec06452014-03-19 11:23:01 -070057 inline bool isEmpty() const { return isEmpty(value); }
58
59 static inline bool isEmpty(uint32_t value) { return ! value; }
Jeff Brown66db6892010-04-22 18:58:52 -070060
Jeff Brown82e14f62011-07-01 17:59:27 -070061 // Returns true if the bit set does not contain any unmarked bits.
Michael Wright2ec06452014-03-19 11:23:01 -070062 inline bool isFull() const { return isFull(value); }
63
64 static inline bool isFull(uint32_t value) { return value == 0xffffffffUL; }
Jeff Brown82e14f62011-07-01 17:59:27 -070065
Jeff Brown66db6892010-04-22 18:58:52 -070066 // Returns true if the specified bit is marked.
Michael Wright2ec06452014-03-19 11:23:01 -070067 inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
68
69 static inline bool hasBit(uint32_t value, uint32_t n) { return value & valueForBit(n); }
Jeff Brown66db6892010-04-22 18:58:52 -070070
71 // Marks the specified bit.
Michael Wright2ec06452014-03-19 11:23:01 -070072 inline void markBit(uint32_t n) { markBit(value, n); }
73
74 static inline void markBit (uint32_t& value, uint32_t n) { value |= valueForBit(n); }
Jeff Brown66db6892010-04-22 18:58:52 -070075
76 // Clears the specified bit.
Michael Wright2ec06452014-03-19 11:23:01 -070077 inline void clearBit(uint32_t n) { clearBit(value, n); }
78
79 static inline void clearBit(uint32_t& value, uint32_t n) { value &= ~ valueForBit(n); }
Jeff Brown66db6892010-04-22 18:58:52 -070080
81 // Finds the first marked bit in the set.
82 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -070083 inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
84
Andreas Gampe02c94602014-04-11 18:23:11 -070085 static uint32_t firstMarkedBit(uint32_t value) { return clz_checked(value); }
Jeff Brown66db6892010-04-22 18:58:52 -070086
87 // Finds the first unmarked bit in the set.
88 // Result is undefined if all bits are marked.
Michael Wright2ec06452014-03-19 11:23:01 -070089 inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
90
Andreas Gampe02c94602014-04-11 18:23:11 -070091 static inline uint32_t firstUnmarkedBit(uint32_t value) { return clz_checked(~ value); }
Jeff Brown66db6892010-04-22 18:58:52 -070092
Jeff Brown5e353702011-03-14 19:39:54 -070093 // Finds the last marked bit in the set.
94 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -070095 inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
96
Andreas Gampe02c94602014-04-11 18:23:11 -070097 static inline uint32_t lastMarkedBit(uint32_t value) { return 31 - ctz_checked(value); }
Jeff Brown5e353702011-03-14 19:39:54 -070098
Jeff Brown4ccb2fc2011-07-27 16:04:54 -070099 // Finds the first marked bit in the set and clears it. Returns the bit index.
100 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700101 inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
102
103 static inline uint32_t clearFirstMarkedBit(uint32_t& value) {
104 uint32_t n = firstMarkedBit(value);
105 clearBit(value, n);
Jeff Brown4ccb2fc2011-07-27 16:04:54 -0700106 return n;
107 }
108
109 // Finds the first unmarked bit in the set and marks it. Returns the bit index.
110 // Result is undefined if all bits are marked.
Michael Wright2ec06452014-03-19 11:23:01 -0700111 inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
112
113 static inline uint32_t markFirstUnmarkedBit(uint32_t& value) {
114 uint32_t n = firstUnmarkedBit(value);
115 markBit(value, n);
Jeff Brown4ccb2fc2011-07-27 16:04:54 -0700116 return n;
117 }
118
119 // Finds the last marked bit in the set and clears it. Returns the bit index.
120 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700121 inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
122
123 static inline uint32_t clearLastMarkedBit(uint32_t& value) {
124 uint32_t n = lastMarkedBit(value);
125 clearBit(value, n);
Jeff Brown4ccb2fc2011-07-27 16:04:54 -0700126 return n;
127 }
128
Jeff Brown9ae794d2011-03-09 17:39:48 -0800129 // Gets the index of the specified bit in the set, which is the number of
130 // marked bits that appear before the specified bit.
131 inline uint32_t getIndexOfBit(uint32_t n) const {
Michael Wright2ec06452014-03-19 11:23:01 -0700132 return getIndexOfBit(value, n);
133 }
134
135 static inline uint32_t getIndexOfBit(uint32_t value, uint32_t n) {
Michael Wright23e13632020-07-12 00:07:14 +0100136 return static_cast<uint32_t>(__builtin_popcountl(value & ~(0xffffffffUL >> n)));
Jeff Brown9ae794d2011-03-09 17:39:48 -0800137 }
138
Jeff Brown66db6892010-04-22 18:58:52 -0700139 inline bool operator== (const BitSet32& other) const { return value == other.value; }
140 inline bool operator!= (const BitSet32& other) const { return value != other.value; }
Michael Wrightd614ee42013-05-21 14:11:34 -0700141 inline BitSet32 operator& (const BitSet32& other) const {
142 return BitSet32(value & other.value);
143 }
144 inline BitSet32& operator&= (const BitSet32& other) {
145 value &= other.value;
146 return *this;
147 }
148 inline BitSet32 operator| (const BitSet32& other) const {
149 return BitSet32(value | other.value);
150 }
151 inline BitSet32& operator|= (const BitSet32& other) {
152 value |= other.value;
153 return *this;
154 }
Andreas Gampe02c94602014-04-11 18:23:11 -0700155
156private:
157 // We use these helpers as the signature of __builtin_c{l,t}z has "unsigned int" for the
158 // input, which is only guaranteed to be 16b, not 32. The compiler should optimize this away.
159 static inline uint32_t clz_checked(uint32_t value) {
160 if (sizeof(unsigned int) == sizeof(uint32_t)) {
Michael Wright23e13632020-07-12 00:07:14 +0100161 return static_cast<uint32_t>(__builtin_clz(value));
Andreas Gampe02c94602014-04-11 18:23:11 -0700162 } else {
Michael Wright23e13632020-07-12 00:07:14 +0100163 return static_cast<uint32_t>(__builtin_clzl(value));
Andreas Gampe02c94602014-04-11 18:23:11 -0700164 }
165 }
166
167 static inline uint32_t ctz_checked(uint32_t value) {
168 if (sizeof(unsigned int) == sizeof(uint32_t)) {
Michael Wright23e13632020-07-12 00:07:14 +0100169 return static_cast<uint32_t>(__builtin_ctz(value));
Andreas Gampe02c94602014-04-11 18:23:11 -0700170 } else {
Michael Wright23e13632020-07-12 00:07:14 +0100171 return static_cast<uint32_t>(__builtin_ctzl(value));
Andreas Gampe02c94602014-04-11 18:23:11 -0700172 }
173 }
Jeff Brown66db6892010-04-22 18:58:52 -0700174};
175
Jeff Brown9a0a76d2012-03-16 14:45:49 -0700176ANDROID_BASIC_TYPES_TRAITS(BitSet32)
177
Michael Wrightbab6ea02014-03-18 17:25:20 -0700178// A simple set of 64 bits that can be individually marked or cleared.
179struct BitSet64 {
180 uint64_t value;
181
182 inline BitSet64() : value(0ULL) { }
183 explicit inline BitSet64(uint64_t value) : value(value) { }
184
185 // Gets the value associated with a particular bit index.
186 static inline uint64_t valueForBit(uint32_t n) { return 0x8000000000000000ULL >> n; }
187
188 // Clears the bit set.
Michael Wright2ec06452014-03-19 11:23:01 -0700189 inline void clear() { clear(value); }
190
191 static inline void clear(uint64_t& value) { value = 0ULL; }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700192
193 // Returns the number of marked bits in the set.
Michael Wright2ec06452014-03-19 11:23:01 -0700194 inline uint32_t count() const { return count(value); }
195
Michael Wright23e13632020-07-12 00:07:14 +0100196 static inline uint32_t count(uint64_t value) {
197 return static_cast<uint32_t>(__builtin_popcountll(value));
198 }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700199
200 // Returns true if the bit set does not contain any marked bits.
Michael Wright2ec06452014-03-19 11:23:01 -0700201 inline bool isEmpty() const { return isEmpty(value); }
202
203 static inline bool isEmpty(uint64_t value) { return ! value; }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700204
205 // Returns true if the bit set does not contain any unmarked bits.
Michael Wright2ec06452014-03-19 11:23:01 -0700206 inline bool isFull() const { return isFull(value); }
207
208 static inline bool isFull(uint64_t value) { return value == 0xffffffffffffffffULL; }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700209
210 // Returns true if the specified bit is marked.
Michael Wright2ec06452014-03-19 11:23:01 -0700211 inline bool hasBit(uint32_t n) const { return hasBit(value, n); }
212
213 static inline bool hasBit(uint64_t value, uint32_t n) { return value & valueForBit(n); }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700214
215 // Marks the specified bit.
Michael Wright2ec06452014-03-19 11:23:01 -0700216 inline void markBit(uint32_t n) { markBit(value, n); }
217
218 static inline void markBit(uint64_t& value, uint32_t n) { value |= valueForBit(n); }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700219
220 // Clears the specified bit.
Michael Wright2ec06452014-03-19 11:23:01 -0700221 inline void clearBit(uint32_t n) { clearBit(value, n); }
222
223 static inline void clearBit(uint64_t& value, uint32_t n) { value &= ~ valueForBit(n); }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700224
225 // Finds the first marked bit in the set.
226 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700227 inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }
228
Michael Wright23e13632020-07-12 00:07:14 +0100229 static inline uint32_t firstMarkedBit(uint64_t value) {
230 return static_cast<uint32_t>(__builtin_clzll(value));
231 }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700232
233 // Finds the first unmarked bit in the set.
234 // Result is undefined if all bits are marked.
Michael Wright2ec06452014-03-19 11:23:01 -0700235 inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }
236
Michael Wright23e13632020-07-12 00:07:14 +0100237 static inline uint32_t firstUnmarkedBit(uint64_t value) {
238 return static_cast<uint32_t>(__builtin_clzll(~value));
239 }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700240
241 // Finds the last marked bit in the set.
242 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700243 inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }
244
Michael Wright23e13632020-07-12 00:07:14 +0100245 static inline uint32_t lastMarkedBit(uint64_t value) {
246 return static_cast<uint32_t>(63 - __builtin_ctzll(value));
247 }
Michael Wrightbab6ea02014-03-18 17:25:20 -0700248
249 // Finds the first marked bit in the set and clears it. Returns the bit index.
250 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700251 inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }
252
253 static inline uint32_t clearFirstMarkedBit(uint64_t& value) {
Michael Wright23e13632020-07-12 00:07:14 +0100254 uint32_t n = firstMarkedBit(value);
Michael Wright2ec06452014-03-19 11:23:01 -0700255 clearBit(value, n);
Michael Wrightbab6ea02014-03-18 17:25:20 -0700256 return n;
257 }
258
259 // Finds the first unmarked bit in the set and marks it. Returns the bit index.
260 // Result is undefined if all bits are marked.
Michael Wright2ec06452014-03-19 11:23:01 -0700261 inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }
262
263 static inline uint32_t markFirstUnmarkedBit(uint64_t& value) {
Michael Wright23e13632020-07-12 00:07:14 +0100264 uint32_t n = firstUnmarkedBit(value);
Michael Wright2ec06452014-03-19 11:23:01 -0700265 markBit(value, n);
Michael Wrightbab6ea02014-03-18 17:25:20 -0700266 return n;
267 }
268
269 // Finds the last marked bit in the set and clears it. Returns the bit index.
270 // Result is undefined if all bits are unmarked.
Michael Wright2ec06452014-03-19 11:23:01 -0700271 inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }
272
273 static inline uint32_t clearLastMarkedBit(uint64_t& value) {
Michael Wright23e13632020-07-12 00:07:14 +0100274 uint32_t n = lastMarkedBit(value);
Michael Wright2ec06452014-03-19 11:23:01 -0700275 clearBit(value, n);
Michael Wrightbab6ea02014-03-18 17:25:20 -0700276 return n;
277 }
278
279 // Gets the index of the specified bit in the set, which is the number of
280 // marked bits that appear before the specified bit.
Michael Wright2ec06452014-03-19 11:23:01 -0700281 inline uint32_t getIndexOfBit(uint32_t n) const { return getIndexOfBit(value, n); }
282
283 static inline uint32_t getIndexOfBit(uint64_t value, uint32_t n) {
Michael Wright23e13632020-07-12 00:07:14 +0100284 return static_cast<uint32_t>(__builtin_popcountll(value & ~(0xffffffffffffffffULL >> n)));
Michael Wrightbab6ea02014-03-18 17:25:20 -0700285 }
286
287 inline bool operator== (const BitSet64& other) const { return value == other.value; }
288 inline bool operator!= (const BitSet64& other) const { return value != other.value; }
289 inline BitSet64 operator& (const BitSet64& other) const {
290 return BitSet64(value & other.value);
291 }
292 inline BitSet64& operator&= (const BitSet64& other) {
293 value &= other.value;
294 return *this;
295 }
296 inline BitSet64 operator| (const BitSet64& other) const {
297 return BitSet64(value | other.value);
298 }
299 inline BitSet64& operator|= (const BitSet64& other) {
300 value |= other.value;
301 return *this;
302 }
303};
304
Michael Wright74e25382014-03-18 17:45:37 -0700305ANDROID_BASIC_TYPES_TRAITS(BitSet64)
Michael Wrightbab6ea02014-03-18 17:25:20 -0700306
Jeff Brown66db6892010-04-22 18:58:52 -0700307} // namespace android
308
309#endif // UTILS_BITSET_H