OR-Tools  9.3
bitset.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include "ortools/util/bitset.h"
15
18
19ABSL_FLAG(int, bitset_small_bitset_count, 8,
20 "threshold to count bits with buckets");
21
22namespace operations_research {
23
24// ---------- Bit Operations ----------
25
26#define BIT_COUNT_RANGE(size, zero) \
27 uint##size##_t BitCountRange##size(const uint##size##_t* const bits, \
28 uint##size##_t start, \
29 uint##size##_t end) { \
30 if (end - start > absl::GetFlag(FLAGS_bitset_small_bitset_count)) { \
31 const int offset_start = BitOffset##size(start); \
32 const int pos_start = BitPos##size(start); \
33 const int offset_end = BitOffset##size(end); \
34 const int pos_end = BitPos##size(end); \
35 if (offset_end == offset_start) { \
36 return BitCount##size(bits[offset_start] & \
37 OneRange##size(pos_start, pos_end)); \
38 } else { \
39 uint##size##_t bit_count = zero; \
40 bit_count += \
41 BitCount##size(bits[offset_start] & IntervalUp##size(pos_start)); \
42 for (int offset = offset_start + 1; offset < offset_end; ++offset) { \
43 bit_count += BitCount##size(bits[offset]); \
44 } \
45 bit_count += \
46 BitCount##size(bits[offset_end] & IntervalDown##size(pos_end)); \
47 return bit_count; \
48 } \
49 } else { \
50 uint##size##_t bit_count = zero; \
51 for (uint##size##_t i = start; i <= end; ++i) { \
52 bit_count += IsBitSet##size(bits, i); \
53 } \
54 return bit_count; \
55 } \
56 }
57
58BIT_COUNT_RANGE(64, uint64_t{0})
59BIT_COUNT_RANGE(32, 0U)
60
61#undef BIT_COUNT_RANGE
62
63#define IS_EMPTY_RANGE(size) \
64 bool IsEmptyRange##size(const uint##size##_t* const bits, \
65 uint##size##_t start, uint##size##_t end) { \
66 const int offset_start = BitOffset##size(start); \
67 const int pos_start = BitPos##size(start); \
68 const int offset_end = BitOffset##size(end); \
69 const int pos_end = BitPos##size(end); \
70 if (offset_end == offset_start) { \
71 if (bits[offset_start] & OneRange##size(pos_start, pos_end)) { \
72 return false; \
73 } \
74 } else { \
75 if (bits[offset_start] & IntervalUp##size(pos_start)) { \
76 return false; \
77 } \
78 for (int offset = offset_start + 1; offset < offset_end; ++offset) { \
79 if (bits[offset]) { \
80 return false; \
81 } \
82 } \
83 if (bits[offset_end] & IntervalDown##size(pos_end)) { \
84 return false; \
85 } \
86 } \
87 return true; \
88 }
89
92
93#undef IS_EMPTY_RANGE
94
95#define LEAST_SIGNIFCANT_BIT_POSITION(size) \
96 int##size##_t LeastSignificantBitPosition##size( \
97 const uint##size##_t* const bits, uint##size##_t start, \
98 uint##size##_t end) { \
99 DCHECK_LE(start, end); \
100 if (IsBitSet##size(bits, start)) { \
101 return start; \
102 } \
103 const int offset_start = BitOffset##size(start); \
104 const int offset_end = BitOffset##size(end); \
105 const int pos_start = BitPos##size(start); \
106 if (offset_start == offset_end) { \
107 const int pos_end = BitPos##size(end); \
108 const uint##size##_t active_range = \
109 bits[offset_start] & OneRange##size(pos_start, pos_end); \
110 if (active_range) { \
111 return BitShift##size(offset_start) + \
112 LeastSignificantBitPosition##size(active_range); \
113 } \
114 return -1; \
115 } else { \
116 const uint##size##_t start_mask = \
117 bits[offset_start] & IntervalUp##size(pos_start); \
118 if (start_mask) { \
119 return BitShift##size(offset_start) + \
120 LeastSignificantBitPosition##size(start_mask); \
121 } else { \
122 for (int offset = offset_start + 1; offset < offset_end; ++offset) { \
123 if (bits[offset]) { \
124 return BitShift##size(offset) + \
125 LeastSignificantBitPosition##size(bits[offset]); \
126 } \
127 } \
128 const int pos_end = BitPos##size(end); \
129 const uint##size##_t active_range = \
130 bits[offset_end] & IntervalDown##size(pos_end); \
131 if (active_range) { \
132 return BitShift##size(offset_end) + \
133 LeastSignificantBitPosition##size(active_range); \
134 } else { \
135 return -1; \
136 } \
137 } \
138 } \
139 }
140
143
144#undef LEAST_SIGNIFCANT_BIT_POSITION
145
146#define MOST_SIGNIFICANT_BIT_POSITION(size) \
147 int##size##_t MostSignificantBitPosition##size( \
148 const uint##size##_t* const bits, uint##size##_t start, \
149 uint##size##_t end) { \
150 DCHECK_GE(end, start); \
151 if (IsBitSet##size(bits, end)) { \
152 return end; \
153 } \
154 const int offset_start = BitOffset##size(start); \
155 const int offset_end = BitOffset##size(end); \
156 const int pos_end = BitPos##size(end); \
157 if (offset_start == offset_end) { \
158 const int pos_start = BitPos##size(start); \
159 const uint##size##_t active_range = \
160 bits[offset_start] & OneRange##size(pos_start, pos_end); \
161 if (active_range) { \
162 return BitShift##size(offset_end) + \
163 MostSignificantBitPosition##size(active_range); \
164 } else { \
165 return -1; \
166 } \
167 } else { \
168 const uint##size##_t end_mask = \
169 bits[offset_end] & IntervalDown##size(pos_end); \
170 if (end_mask) { \
171 return BitShift##size(offset_end) + \
172 MostSignificantBitPosition##size(end_mask); \
173 } else { \
174 for (int offset = offset_end - 1; offset > offset_start; --offset) { \
175 if (bits[offset]) { \
176 return BitShift##size(offset) + \
177 MostSignificantBitPosition##size(bits[offset]); \
178 } \
179 } \
180 const int pos_start = BitPos##size(start); \
181 const uint##size##_t active_range = \
182 bits[offset_start] & IntervalUp##size(pos_start); \
183 if (active_range) { \
184 return BitShift##size(offset_start) + \
185 MostSignificantBitPosition##size(active_range); \
186 } else { \
187 return -1; \
188 } \
189 } \
190 } \
191 }
192
195
196#undef MOST_SIGNIFICANT_BIT_POSITION
197
198#define UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION(size) \
199 int##size##_t UnsafeLeastSignificantBitPosition##size( \
200 const uint##size##_t* const bits, uint##size##_t start, \
201 uint##size##_t end) { \
202 DCHECK_LE(start, end); \
203 DCHECK(IsBitSet##size(bits, end)); \
204 if (IsBitSet##size(bits, start)) { \
205 return start; \
206 } \
207 const int offset_start = BitOffset##size(start); \
208 const int offset_end = BitOffset##size(end); \
209 const int pos_start = BitPos##size(start); \
210 const uint##size##_t start_mask = \
211 bits[offset_start] & IntervalUp##size(pos_start); \
212 if (start_mask) { \
213 return BitShift##size(offset_start) + \
214 LeastSignificantBitPosition##size(start_mask); \
215 } \
216 for (int offset = offset_start + 1; offset <= offset_end; ++offset) { \
217 if (bits[offset]) { \
218 return BitShift##size(offset) + \
219 LeastSignificantBitPosition##size(bits[offset]); \
220 } \
221 } \
222 return -1; \
223 }
224
227
228#undef UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION
229
230#define UNSAFE_MOST_SIGNIFICANT_BIT_POSITION(size) \
231 int##size##_t UnsafeMostSignificantBitPosition##size( \
232 const uint##size##_t* const bits, uint##size##_t start, \
233 uint##size##_t end) { \
234 DCHECK_GE(end, start); \
235 DCHECK(IsBitSet##size(bits, start)); \
236 if (IsBitSet##size(bits, end)) { \
237 return end; \
238 } \
239 const int offset_start = BitOffset##size(start); \
240 const int offset_end = BitOffset##size(end); \
241 const int pos_end = BitPos##size(end); \
242 const uint##size##_t end_mask = \
243 bits[offset_end] & IntervalDown##size(pos_end); \
244 if (end_mask) { \
245 return BitShift##size(offset_end) + \
246 MostSignificantBitPosition##size(end_mask); \
247 } \
248 for (int offset = offset_end - 1; offset >= offset_start; --offset) { \
249 if (bits[offset]) { \
250 return BitShift##size(offset) + \
251 MostSignificantBitPosition##size(bits[offset]); \
252 } \
253 } \
254 return -1; \
255 }
256
259
260#undef UNSAFE_MOST_SIGNIFICANT_BIT_POSITION
261
262} // namespace operations_research
#define LEAST_SIGNIFCANT_BIT_POSITION(size)
Definition: bitset.cc:95
#define UNSAFE_MOST_SIGNIFICANT_BIT_POSITION(size)
Definition: bitset.cc:230
#define MOST_SIGNIFICANT_BIT_POSITION(size)
Definition: bitset.cc:146
#define IS_EMPTY_RANGE(size)
Definition: bitset.cc:63
#define BIT_COUNT_RANGE(size, zero)
Definition: bitset.cc:26
ABSL_FLAG(int, bitset_small_bitset_count, 8, "threshold to count bits with buckets")
#define UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION(size)
Definition: bitset.cc:198
Collection of objects used to extend the Constraint Solver library.