Line data Source code
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 : */
27 : const uint8 pg_leftmost_one_pos[256] = {
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 : */
55 : const uint8 pg_rightmost_one_pos[256] = {
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 : */
80 : const uint8 pg_number_of_ones[256] = {
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 : */
103 : int
104 0 : pg_popcount32_portable(uint32 word)
105 : {
106 : #ifdef HAVE__BUILTIN_POPCOUNT
107 0 : 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 : */
125 : int
126 0 : pg_popcount64_portable(uint64 word)
127 : {
128 : #ifdef HAVE__BUILTIN_POPCOUNT
129 : #if SIZEOF_LONG == 8
130 0 : return __builtin_popcountl(word);
131 : #elif SIZEOF_LONG_LONG == 8
132 : return __builtin_popcountll(word);
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 : */
153 : uint64
154 0 : pg_popcount_portable(const char *buf, int bytes)
155 : {
156 0 : uint64 popcnt = 0;
157 :
158 : #if SIZEOF_VOID_P >= 8
159 : /* Process in 64-bit chunks if the buffer is aligned. */
160 0 : if (buf == (const char *) TYPEALIGN(8, buf))
161 : {
162 0 : const uint64 *words = (const uint64 *) buf;
163 :
164 0 : while (bytes >= 8)
165 : {
166 0 : popcnt += pg_popcount64_portable(*words++);
167 0 : bytes -= 8;
168 : }
169 :
170 0 : 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 0 : while (bytes--)
190 0 : popcnt += pg_number_of_ones[(unsigned char) *buf++];
191 :
192 0 : 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 : */
199 : uint64
200 0 : pg_popcount_masked_portable(const char *buf, int bytes, bits8 mask)
201 : {
202 0 : uint64 popcnt = 0;
203 :
204 : #if SIZEOF_VOID_P >= 8
205 : /* Process in 64-bit chunks if the buffer is aligned */
206 0 : uint64 maskv = ~UINT64CONST(0) / 0xFF * mask;
207 :
208 0 : if (buf == (const char *) TYPEALIGN(8, buf))
209 : {
210 0 : const uint64 *words = (const uint64 *) buf;
211 :
212 0 : while (bytes >= 8)
213 : {
214 0 : popcnt += pg_popcount64_portable(*words++ & maskv);
215 0 : bytes -= 8;
216 : }
217 :
218 0 : 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 0 : while (bytes--)
240 0 : popcnt += pg_number_of_ones[(unsigned char) *buf++ & mask];
241 :
242 0 : 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 : */
253 : int
254 : pg_popcount32(uint32 word)
255 : {
256 : return pg_popcount32_portable(word);
257 : }
258 :
259 : int
260 : pg_popcount64(uint64 word)
261 : {
262 : return pg_popcount64_portable(word);
263 : }
264 :
265 : /*
266 : * pg_popcount_optimized
267 : * Returns the number of 1-bits in buf
268 : */
269 : uint64
270 : pg_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 : */
279 : uint64
280 : pg_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 */
|