File: bitops.h

package info (click to toggle)
drgn 0.0.33-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,892 kB
  • sloc: python: 59,081; ansic: 51,400; awk: 423; makefile: 339; sh: 113
file content (177 lines) | stat: -rw-r--r-- 4,406 bytes parent folder | download | duplicates (2)
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
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later

/**
 * @file
 *
 * Bitwise operations.
 *
 * See @ref BitwiseOperations.
 */

#ifndef DRGN_BITOPS_H
#define DRGN_BITOPS_H

#include "pp.h"

/**
 * @ingroup Internals
 *
 * @defgroup BitwiseOperations Bitwise operations
 *
 * Generic bitwise operations.
 *
 * @{
 */

/**
 * Count Trailing Zero bits.
 *
 * Return the number of trailing least significant 0-bits in @p x. This is
 * undefined if @p x is zero.
 *
 * ```
 * ctz(1) == ctz(0b1) == 0
 * ctz(2) == ctz(0b10) == 1
 * ctz(12) == ctz(0b1100) == 2
 * ```
 *
 * @param[in] x Integer.
 */
#define ctz(x) generic_bitop(x, PP_UNIQUE(_x), builtin_bitop_impl, ctz)

/**
 * Find Last Set bit.
 *
 * Return the one-based index of the most significant 1-bit of @p x or 0 if @p x
 * is 0.
 *
 * ```
 * fls(0) == fls(0b0) == 0
 * fls(1) == fls(0b1) == 1
 * fls(13) == fls(0b1101) == 4
 * ```
 *
 * For unsigned integers,
 * ```
 * fls(x) = floor(log2(x)) + 1, if x > 0
 *          0, if x == 0
 * ```
 *
 * @param[in] x Integer.
 */
#define fls(x) generic_bitop(x, PP_UNIQUE(_x), fls_impl,)
/** @cond */
// This doesn't do the normal macro argument safety stuff because it should only
// be used via generic_bitop(), which already does it.
#define fls_impl(arg, suffix, x) (x ? ilog2_impl(, suffix, x) + 1 : 0)

/**
 * Integer base 2 logarithm.
 *
 * Return floor(log2(x)). This is also the zero-based index of the most
 * significant 1-bit of @p x. This is undefined if `x <= 0`.
 *
 * ```
 * ilog2(1) == ilog2(0b1) = 0
 * ilog2(2) == ilog2(0b10) = 1
 * ilog2(3) == ilog2(0b11) = 1
 * ilog2(13) == ilog2(0b1101) = 3
 * ```
 */
#define ilog2(x) generic_bitop(x, PP_UNIQUE(_x), ilog2_impl,)
// The straightfoward implementation is bits - clz - 1, but we can use a trick
// from folly::findLastSet: "If X is a power of two, X - Y = 1 + ((X - 1) ^ Y).
// Doing this transformation allows GCC to remove its own xor that it adds to
// implement clz using bsr."
#define ilog2_impl(arg, suffix, x)	\
	((8 * sizeof(0u##suffix) - 1) ^ __builtin_clz##suffix(x))

/**
 * Bit population count.
 *
 * Return the number of 1-bits in @p x.
 *
 * ```
 * popcount(8) == 1
 * popcount(3) == 2
 * ```
 */
#define popcount(x) generic_bitop(x, PP_UNIQUE(_x), builtin_bitop_impl, popcount)

#define builtin_bitop_impl(arg, suffix, x) __builtin_##arg##suffix(x)
#define generic_bitop(x, unique_x, impl, impl_arg) ({			\
	__auto_type unique_x = (x);					\
	_Static_assert(sizeof(unique_x) <= sizeof(unsigned long long),	\
		       "type is too large");				\
	(unsigned int)(sizeof(unique_x) <= sizeof(unsigned int) ?	\
		       impl(impl_arg, , unique_x) :			\
		       sizeof(unique_x) <= sizeof(unsigned long) ?	\
		       impl(impl_arg, l, unique_x) :			\
		       impl(impl_arg, ll, unique_x));			\
})
/** @endcond */

/**
 * Return whether @p x is a power of two.
 *
 * ```
 * is_power_of_two(0) == 0
 * is_power_of_two(1) == 1
 * is_power_of_two(13) == 0
 * is_power_of_two(32) == 1
 * ```
 *
 * @param[in] x Non-negative integer.
 */
#define is_power_of_two(x) is_power_of_two_impl(x, PP_UNIQUE(_x))
/** @cond */
#define is_power_of_two_impl(x, unique_x) ({		\
	__auto_type unique_x = (x);			\
	unique_x && (unique_x & (unique_x - 1)) == 0;	\
})
/** @endcond */

/**
 * Return the smallest power of two greater than or equal to @p x.
 *
 * ```
 * next_power_of_two(0) == 1 // Zero is not a power of two
 * next_power_of_two(1) == 1
 * next_power_of_two(13) == 16
 * ```
 *
 * @param[in] x Non-negative integer.
 */
#define next_power_of_two(x) next_power_of_two_impl(x, PP_UNIQUE(_x))
/** @cond */
#define next_power_of_two_impl(x, unique_x) ({			\
	__auto_type unique_x = (x);				\
	unique_x ? (typeof(unique_x))1 << fls(unique_x - 1) :	\
	(typeof(unique_x))1;					\
})
/** @endcond */

/**
 * Iterate over each 1-bit in @p mask.
 *
 * On each iteration, this sets @p i to the zero-based index of the least
 * significant 1-bit in @p mask and clears that bit in @p mask. It stops
 * iterating when @p mask is zero.
 *
 * ```
 * // Outputs 0 2 3
 * unsigned int mask = 13, i;
 * for_each_bit(i, mask)
 *         printf("%u ", i);
 * ```
 *
 * @param[out] i Iteration variable name.
 * @param[in,out] mask Integer to iterate over. This is modified.
 */
#define for_each_bit(i, mask)	\
	while (mask && (i = ctz(mask), mask &= mask - 1, 1))

/** @} */

#endif /* DRGN_BITOPS_H */