PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_bitutils.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_bitutils.c
4 * Miscellaneous functions for bit-wise operations.
5 *
6 * Copyright (c) 2019-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/port/pg_bitutils.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "c.h"
14
15#include "port/pg_bitutils.h"
16
17
18/*
19 * Array giving the position of the left-most set bit for each possible
20 * byte value. We count the right-most position as the 0th bit, and the
21 * left-most the 7th bit. The 0th entry of the array should not be used.
22 *
23 * Note: this is not used by the functions in pg_bitutils.h when
24 * HAVE__BUILTIN_CLZ is defined, but we provide it anyway, so that
25 * extensions possibly compiled with a different compiler can use it.
26 */
28 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
29 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
30 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
31 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
32 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
33 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
34 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
35 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
36 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
37 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
38 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
39 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
40 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
41 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
42 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
43 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
44};
45
46/*
47 * Array giving the position of the right-most set bit for each possible
48 * byte value. We count the right-most position as the 0th bit, and the
49 * left-most the 7th bit. The 0th entry of the array should not be used.
50 *
51 * Note: this is not used by the functions in pg_bitutils.h when
52 * HAVE__BUILTIN_CTZ is defined, but we provide it anyway, so that
53 * extensions possibly compiled with a different compiler can use it.
54 */
56 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
57 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
58 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
59 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
60 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
61 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
62 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
63 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
64 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
65 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
66 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
67 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
68 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
69 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
70 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
71 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
72};
73
74/*
75 * Array giving the number of 1-bits in each possible byte value.
76 *
77 * Note: we export this for use by functions in which explicit use
78 * of the popcount functions seems unlikely to be a win.
79 */
81 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
82 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
83 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
84 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
85 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
86 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
87 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
88 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
89 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
90 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
91 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
92 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
93 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
94 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
95 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
96 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
97};
98
99/*
100 * pg_popcount32_portable
101 * Return the number of 1 bits set in word
102 */
103int
105{
106#ifdef HAVE__BUILTIN_POPCOUNT
107 return __builtin_popcount(word);
108#else /* !HAVE__BUILTIN_POPCOUNT */
109 int result = 0;
110
111 while (word != 0)
112 {
113 result += pg_number_of_ones[word & 255];
114 word >>= 8;
115 }
116
117 return result;
118#endif /* HAVE__BUILTIN_POPCOUNT */
119}
120
121/*
122 * pg_popcount64_portable
123 * Return the number of 1 bits set in word
124 */
125int
127{
128#ifdef HAVE__BUILTIN_POPCOUNT
129#if SIZEOF_LONG == 8
131#elif SIZEOF_LONG_LONG == 8
133#else
134#error "cannot find integer of the same size as uint64_t"
135#endif
136#else /* !HAVE__BUILTIN_POPCOUNT */
137 int result = 0;
138
139 while (word != 0)
140 {
141 result += pg_number_of_ones[word & 255];
142 word >>= 8;
143 }
144
145 return result;
146#endif /* HAVE__BUILTIN_POPCOUNT */
147}
148
149/*
150 * pg_popcount_portable
151 * Returns the number of 1-bits in buf
152 */
153uint64
154pg_popcount_portable(const char *buf, int bytes)
155{
156 uint64 popcnt = 0;
157
158#if SIZEOF_VOID_P >= 8
159 /* Process in 64-bit chunks if the buffer is aligned. */
160 if (buf == (const char *) TYPEALIGN(8, buf))
161 {
162 const uint64 *words = (const uint64 *) buf;
163
164 while (bytes >= 8)
165 {
166 popcnt += pg_popcount64_portable(*words++);
167 bytes -= 8;
168 }
169
170 buf = (const char *) words;
171 }
172#else
173 /* Process in 32-bit chunks if the buffer is aligned. */
174 if (buf == (const char *) TYPEALIGN(4, buf))
175 {
176 const uint32 *words = (const uint32 *) buf;
177
178 while (bytes >= 4)
179 {
180 popcnt += pg_popcount32_portable(*words++);
181 bytes -= 4;
182 }
183
184 buf = (const char *) words;
185 }
186#endif
187
188 /* Process any remaining bytes */
189 while (bytes--)
190 popcnt += pg_number_of_ones[(unsigned char) *buf++];
191
192 return popcnt;
193}
194
195/*
196 * pg_popcount_masked_portable
197 * Returns the number of 1-bits in buf after applying the mask to each byte
198 */
199uint64
200pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask)
201{
202 uint64 popcnt = 0;
203
204#if SIZEOF_VOID_P >= 8
205 /* Process in 64-bit chunks if the buffer is aligned */
206 uint64 maskv = ~UINT64CONST(0) / 0xFF * mask;
207
208 if (buf == (const char *) TYPEALIGN(8, buf))
209 {
210 const uint64 *words = (const uint64 *) buf;
211
212 while (bytes >= 8)
213 {
214 popcnt += pg_popcount64_portable(*words++ & maskv);
215 bytes -= 8;
216 }
217
218 buf = (const char *) words;
219 }
220#else
221 /* Process in 32-bit chunks if the buffer is aligned. */
222 uint32 maskv = ~((uint32) 0) / 0xFF * mask;
223
224 if (buf == (const char *) TYPEALIGN(4, buf))
225 {
226 const uint32 *words = (const uint32 *) buf;
227
228 while (bytes >= 4)
229 {
230 popcnt += pg_popcount32_portable(*words++ & maskv);
231 bytes -= 4;
232 }
233
234 buf = (const char *) words;
235 }
236#endif
237
238 /* Process any remaining bytes */
239 while (bytes--)
240 popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
241
242 return popcnt;
243}
244
245#if !defined(HAVE_X86_64_POPCNTQ) && !defined(USE_NEON)
246
247/*
248 * When special CPU instructions are not available, there's no point in using
249 * function pointers to vary the implementation. We instead just make these
250 * actual external functions. The compiler should be able to inline the
251 * portable versions here.
252 */
253int
258
259int
264
265/*
266 * pg_popcount_optimized
267 * Returns the number of 1-bits in buf
268 */
269uint64
270pg_popcount_optimized(const char *buf, int bytes)
271{
272 return pg_popcount_portable(buf, bytes);
273}
274
275/*
276 * pg_popcount_masked_optimized
277 * Returns the number of 1-bits in buf after applying the mask to each byte
278 */
279uint64
280pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask)
281{
282 return pg_popcount_masked_portable(buf, bytes, mask);
283}
284
285#endif /* ! HAVE_X86_64_POPCNTQ && ! USE_NEON */
#define TYPEALIGN(ALIGNVAL, LEN)
Definition c.h:819
uint8_t uint8
Definition c.h:544
uint8 bits8
Definition c.h:553
uint64_t uint64
Definition c.h:547
uint32_t uint32
Definition c.h:546
uint64 pg_popcount_portable(const char *buf, int bytes)
const uint8 pg_number_of_ones[256]
Definition pg_bitutils.c:80
uint64 pg_popcount_masked_optimized(const char *buf, int bytes, bits8 mask)
uint64 pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask)
uint64 pg_popcount_optimized(const char *buf, int bytes)
int pg_popcount64(uint64 word)
int pg_popcount32(uint32 word)
int pg_popcount32_portable(uint32 word)
const uint8 pg_rightmost_one_pos[256]
Definition pg_bitutils.c:55
const uint8 pg_leftmost_one_pos[256]
Definition pg_bitutils.c:27
int pg_popcount64_portable(uint64 word)
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int fb(int x)
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition regcomp.c:1476