MySQL 8.0.40
Source Code Documentation
bit_utils.h
Go to the documentation of this file.
1/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef SQL_JOIN_OPTIMIZER_BIT_UTILS_H
25#define SQL_JOIN_OPTIMIZER_BIT_UTILS_H 1
26
27#include <assert.h>
28#include <stddef.h>
29#include <stdint.h>
30#include <string.h>
31#include "my_compiler.h"
32#ifdef _MSC_VER
33#include <intrin.h>
34#pragma intrinsic(_BitScanForward64)
35#pragma intrinsic(_BitScanReverse64)
36#endif
37
38// Wraps iteration over interesting states (based on the given policy) over a
39// single uint64_t into an STL-style adapter.
40template <class Policy>
42 public:
43 class iterator {
44 private:
45 uint64_t m_state;
46
47 public:
48 explicit iterator(uint64_t state) : m_state(state) {}
49 bool operator==(const iterator &other) const {
50 return m_state == other.m_state;
51 }
52 bool operator!=(const iterator &other) const {
53 return m_state != other.m_state;
54 }
55 size_t operator*() const { return Policy::NextValue(m_state); }
57 m_state = Policy::AdvanceState(m_state);
58 return *this;
59 }
60 };
61
62 explicit BitIteratorAdaptor(uint64_t state) : m_initial_state(state) {}
63
65 iterator end() const { return iterator{0}; }
66
67 private:
68 const uint64_t m_initial_state;
69};
70
71inline size_t FindLowestBitSet(uint64_t x) {
72 assert(x != 0);
73#ifdef _MSC_VER
74 unsigned long idx;
75 _BitScanForward64(&idx, x);
76 return idx;
77#elif defined(__GNUC__) && defined(__x86_64__)
78 // Using this instead of ffsll() (which maps to the same instruction,
79 // but has an extra zero test and returns an int value) helps
80 // a whopping 10% on some of the microbenchmarks! (GCC 9.2, Skylake.)
81 // Evidently, the test for zero is rewritten into a conditional move,
82 // which turns out to be add a lot of latency into these hot loops.
83 size_t idx;
84 asm("bsfq %1,%q0" : "=r"(idx) : "rm"(x));
85 return idx;
86#else
87 // The cast to unsigned at least gets rid of the sign extension.
88 return static_cast<unsigned>(ffsll(x)) - 1u;
89#endif
90}
91
92// A policy for BitIteratorAdaptor that gives out the index of each set bit in
93// the value, ascending.
95 public:
96 static size_t NextValue(uint64_t state) {
97 // Find the lowest set bit.
98 return FindLowestBitSet(state);
99 }
100
101 static uint64_t AdvanceState(uint64_t state) {
102 // Clear the lowest set bit.
103 assert(state != 0);
104 return state & (state - 1);
105 }
106};
107
108// Same as CountBitsAscending, just descending.
110 public:
111 static size_t NextValue(uint64_t state) {
112 // Find the lowest set bit.
113 assert(state != 0);
114#ifdef _MSC_VER
115 unsigned long idx;
116 _BitScanReverse64(&idx, state);
117 return idx;
118#else
119 return __builtin_clzll(state) ^ 63u;
120#endif
121 }
122
123 static uint64_t AdvanceState(uint64_t state) {
124 // Clear the highest set bit. (This is fewer operations
125 // then the standard bit-fiddling trick, especially given
126 // that NextValue() is probably already computed.)
127 return state & ~(uint64_t{1} << NextValue(state));
128 }
129};
130
133}
135 uint64_t state) {
137}
138
139// An iterator (for range-based for loops) that returns all non-zero subsets of
140// a given set. This includes the set itself.
141//
142// In the database literature, this algorithm is often attributed to
143// a 1995 paper of Vance and Maier, but it is known to be older than
144// that. In particular, here is a 1994 reference from Marcel van Kervinck:
145//
146// https://groups.google.com/forum/#!msg/rec.games.chess/KnJvBnhgDKU/yCi5yBx18PQJ
148 public:
149 class iterator {
150 private:
151 uint64_t m_state;
152 uint64_t m_set;
153
154 public:
155 iterator(uint64_t state, uint64_t set) : m_state(state), m_set(set) {}
156 bool operator==(const iterator &other) const {
157 assert(m_set == other.m_set);
158 return m_state == other.m_state;
159 }
160 bool operator!=(const iterator &other) const {
161 assert(m_set == other.m_set);
162 return m_state != other.m_state;
163 }
164 uint64_t operator*() const { return m_state; }
166 m_state = (m_state - m_set) & m_set;
167 return *this;
168 }
169 };
170
171 explicit NonzeroSubsetsOf(uint64_t set) : m_set(set) {}
172
174 // Suppress warning C4146 unary minus operator applied to unsigned type,
175 // result still unsigned
177 iterator begin() const { return {(-m_set) & m_set, m_set}; }
179 iterator end() const { return {0, m_set}; }
180
181 private:
182 const uint64_t m_set;
183};
184
185// Returns a bitmap representing a single table.
186constexpr uint64_t TableBitmap(unsigned x) { return uint64_t{1} << x; }
187
188// Returns a bitmap representing multiple tables.
189template <typename... Args>
190constexpr uint64_t TableBitmap(unsigned first, Args... rest) {
191 return TableBitmap(first) | TableBitmap(rest...);
192}
193
194// Returns a bitmap representing the semi-open interval [start, end).
196// Suppress warning C4146 unary minus operator applied to unsigned type,
197// result still unsigned
199inline uint64_t BitsBetween(unsigned start, unsigned end) {
200 assert(end >= start);
201 assert(end <= 64);
202 if (end == 64) {
203 if (start == 64) {
204 return 0;
205 } else {
206 return -(uint64_t{1} << start);
207 }
208 } else {
209 return (uint64_t{1} << end) - (uint64_t{1} << start);
210 }
211}
213
214// The same, just with a different name for clarity.
215inline uint64_t TablesBetween(unsigned start, unsigned end) {
216 return BitsBetween(start, end);
217}
218
219// Isolates the LSB of x. Ie., if x = 0b110001010, returns 0b000000010.
220// Zero input gives zero output.
222// Suppress warning C4146 unary minus operator applied to unsigned type,
223// result still unsigned
225inline uint64_t IsolateLowestBit(uint64_t x) { return x & (-x); }
227
228// Returns whether X is a subset of Y.
229inline bool IsSubset(uint64_t x, uint64_t y) { return (x & y) == x; }
230
231/// Returns whether X is a proper subset of Y.
232inline bool IsProperSubset(uint64_t x, uint64_t y) {
233 return IsSubset(x, y) && x != y;
234}
235
236// Returns whether X and Y overlap. Symmetric.
237inline bool Overlaps(uint64_t x, uint64_t y) { return (x & y) != 0; }
238
239// Returns whether X has more than one bit set.
240inline bool AreMultipleBitsSet(uint64_t x) { return (x & (x - 1)) != 0; }
241
242// Returns whether X has exactly one bit set.
243inline bool IsSingleBitSet(uint64_t x) {
244 return x != 0 && !AreMultipleBitsSet(x);
245}
246
247// Returns whether the given bit is set in X.
248inline bool IsBitSet(int bit_num, uint64_t x) {
249 return Overlaps(x, uint64_t{1} << bit_num);
250}
251
252// Fairly slow implementation of population count (number of bits set).
253inline int PopulationCount(uint64_t x) {
254 int count = 0;
255 while (x != 0) {
256 x &= x - 1;
257 ++count;
258 }
259 return count;
260}
261
262#endif // SQL_JOIN_OPTIMIZER_BIT_UTILS_H
bool IsProperSubset(uint64_t x, uint64_t y)
Returns whether X is a proper subset of Y.
Definition: bit_utils.h:232
uint64_t TablesBetween(unsigned start, unsigned end)
Definition: bit_utils.h:215
bool AreMultipleBitsSet(uint64_t x)
Definition: bit_utils.h:240
bool IsSingleBitSet(uint64_t x)
Definition: bit_utils.h:243
BitIteratorAdaptor< CountBitsDescending > BitsSetInDescending(uint64_t state)
Definition: bit_utils.h:134
bool IsSubset(uint64_t x, uint64_t y)
Definition: bit_utils.h:229
constexpr uint64_t TableBitmap(unsigned x)
Definition: bit_utils.h:186
uint64_t IsolateLowestBit(uint64_t x)
Definition: bit_utils.h:225
bool Overlaps(uint64_t x, uint64_t y)
Definition: bit_utils.h:237
uint64_t BitsBetween(unsigned start, unsigned end)
Definition: bit_utils.h:199
bool IsBitSet(int bit_num, uint64_t x)
Definition: bit_utils.h:248
int PopulationCount(uint64_t x)
Definition: bit_utils.h:253
BitIteratorAdaptor< CountBitsAscending > BitsSetIn(uint64_t state)
Definition: bit_utils.h:131
size_t FindLowestBitSet(uint64_t x)
Definition: bit_utils.h:71
Definition: bit_utils.h:43
bool operator!=(const iterator &other) const
Definition: bit_utils.h:52
iterator & operator++()
Definition: bit_utils.h:56
size_t operator*() const
Definition: bit_utils.h:55
uint64_t m_state
Definition: bit_utils.h:45
bool operator==(const iterator &other) const
Definition: bit_utils.h:49
iterator(uint64_t state)
Definition: bit_utils.h:48
Definition: bit_utils.h:41
const uint64_t m_initial_state
Definition: bit_utils.h:68
BitIteratorAdaptor(uint64_t state)
Definition: bit_utils.h:62
iterator begin() const
Definition: bit_utils.h:64
iterator end() const
Definition: bit_utils.h:65
Definition: bit_utils.h:94
static size_t NextValue(uint64_t state)
Definition: bit_utils.h:96
static uint64_t AdvanceState(uint64_t state)
Definition: bit_utils.h:101
Definition: bit_utils.h:109
static size_t NextValue(uint64_t state)
Definition: bit_utils.h:111
static uint64_t AdvanceState(uint64_t state)
Definition: bit_utils.h:123
Definition: bit_utils.h:149
bool operator!=(const iterator &other) const
Definition: bit_utils.h:160
uint64_t m_state
Definition: bit_utils.h:151
iterator & operator++()
Definition: bit_utils.h:165
uint64_t operator*() const
Definition: bit_utils.h:164
iterator(uint64_t state, uint64_t set)
Definition: bit_utils.h:155
uint64_t m_set
Definition: bit_utils.h:152
bool operator==(const iterator &other) const
Definition: bit_utils.h:156
Definition: bit_utils.h:147
NonzeroSubsetsOf(uint64_t set)
Definition: bit_utils.h:171
iterator end() const
Definition: bit_utils.h:179
const uint64_t m_set
Definition: bit_utils.h:182
iterator begin() const
Definition: bit_utils.h:177
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:177
Header for compiler-dependent features.
#define MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(X)
Definition: my_compiler.h:266
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:296
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:297
static int count
Definition: myisam_ftdump.cc:43
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:192
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2883