00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "util/bitset.h"
00015
00016 #include "base/commandlineflags.h"
00017 #include "base/logging.h"
00018
00019 DEFINE_int32(bitset_small_bitset_count, 8,
00020 "threshold to count bits with buckets");
00021
00022 namespace operations_research {
00023
00024
00025
00026 #define BIT_COUNT_RANGE(size, zero) \
00027 uint##size BitCountRange##size( \
00028 const uint##size* const bits, uint##size start, uint##size end) { \
00029 if (end - start > FLAGS_bitset_small_bitset_count) { \
00030 const int offset_start = BitOffset##size(start); \
00031 const int pos_start = BitPos##size(start); \
00032 const int offset_end = BitOffset##size(end); \
00033 const int pos_end = BitPos##size(end); \
00034 if (offset_end == offset_start) { \
00035 return BitCount##size(bits[offset_start] \
00036 & OneRange##size(pos_start, pos_end)); \
00037 } else { \
00038 uint##size bit_count = zero; \
00039 bit_count += BitCount##size(bits[offset_start] \
00040 & IntervalUp##size(pos_start)); \
00041 for (int offset = offset_start + 1; \
00042 offset < offset_end; \
00043 ++offset) { \
00044 bit_count += BitCount##size(bits[offset]); \
00045 } \
00046 bit_count += BitCount##size(bits[offset_end] \
00047 & IntervalDown##size(pos_end)); \
00048 return bit_count; \
00049 } \
00050 } else { \
00051 uint##size bit_count = zero; \
00052 for (uint##size i = start; i <= end; ++i) { \
00053 bit_count += IsBitSet##size(bits, i); \
00054 } \
00055 return bit_count; \
00056 } \
00057 }
00058
00059 BIT_COUNT_RANGE(64, GG_ULONGLONG(0))
00060 BIT_COUNT_RANGE(32, 0U)
00061
00062 #undef BIT_COUNT_RANGE
00063
00064 #define IS_EMPTY_RANGE(size) \
00065 bool IsEmptyRange##size(const uint##size* const bits, \
00066 uint##size start, uint##size end) { \
00067 const int offset_start = BitOffset##size(start); \
00068 const int pos_start = BitPos##size(start); \
00069 const int offset_end = BitOffset##size(end); \
00070 const int pos_end = BitPos##size(end); \
00071 if (offset_end == offset_start) { \
00072 if (bits[offset_start] & OneRange##size(pos_start, pos_end)) { \
00073 return false; \
00074 } \
00075 } else { \
00076 if (bits[offset_start] & IntervalUp##size(pos_start)) { \
00077 return false; \
00078 } \
00079 for (int offset = offset_start + 1; \
00080 offset < offset_end; \
00081 ++offset) { \
00082 if (bits[offset]) { \
00083 return false; \
00084 } \
00085 } \
00086 if (bits[offset_end] & IntervalDown##size(pos_end)) { \
00087 return false; \
00088 } \
00089 } \
00090 return true; \
00091 }
00092
00093 IS_EMPTY_RANGE(64)
00094 IS_EMPTY_RANGE(32)
00095
00096 #undef IS_EMPTY_RANGE
00097
00098 #define LEAST_SIGNIFCANT_BIT_POSITION(size) \
00099 int##size LeastSignificantBitPosition##size( \
00100 const uint##size* const bits, uint##size start, uint##size end) { \
00101 DCHECK_LE(start, end); \
00102 if (IsBitSet##size(bits, start)) { \
00103 return start; \
00104 } \
00105 const int offset_start = BitOffset##size(start); \
00106 const int offset_end = BitOffset##size(end); \
00107 const int pos_start = BitPos##size(start); \
00108 if (offset_start == offset_end) { \
00109 const int pos_end = BitPos##size(end); \
00110 const uint##size active_range = \
00111 bits[offset_start] & OneRange##size(pos_start, pos_end); \
00112 if (active_range) { \
00113 return BitShift##size(offset_start) \
00114 + LeastSignificantBitPosition##size(active_range); \
00115 } \
00116 return -1; \
00117 } else { \
00118 const uint##size start_mask = bits[offset_start] \
00119 & IntervalUp##size(pos_start); \
00120 if (start_mask) { \
00121 return BitShift##size(offset_start) \
00122 + LeastSignificantBitPosition##size(start_mask); \
00123 } else { \
00124 for (int offset = offset_start + 1; \
00125 offset < offset_end; \
00126 ++offset) { \
00127 if (bits[offset]) { \
00128 return BitShift##size(offset) \
00129 + LeastSignificantBitPosition##size(bits[offset]); \
00130 } \
00131 } \
00132 const int pos_end = BitPos##size(end); \
00133 const uint##size active_range = bits[offset_end] \
00134 & IntervalDown##size(pos_end); \
00135 if (active_range) { \
00136 return BitShift##size(offset_end) \
00137 + LeastSignificantBitPosition##size(active_range); \
00138 } else { \
00139 return -1; \
00140 } \
00141 } \
00142 } \
00143 }
00144
00145 LEAST_SIGNIFCANT_BIT_POSITION(64)
00146 LEAST_SIGNIFCANT_BIT_POSITION(32)
00147
00148 #undef LEAST_SIGNIFCANT_BIT_POSITION
00149
00150 #define MOST_SIGNIFICANT_BIT_POSITION(size) \
00151 int##size MostSignificantBitPosition##size( \
00152 const uint##size* const bits, \
00153 uint##size start, uint##size end) { \
00154 DCHECK_GE(end, start); \
00155 if (IsBitSet##size(bits, end)) { \
00156 return end; \
00157 } \
00158 const int offset_start = BitOffset##size(start); \
00159 const int offset_end = BitOffset##size(end); \
00160 const int pos_end = BitPos##size(end); \
00161 if (offset_start == offset_end) { \
00162 const int pos_start = BitPos##size(start); \
00163 const uint##size active_range = \
00164 bits[offset_start] & OneRange##size(pos_start, pos_end); \
00165 if (active_range) { \
00166 return BitShift##size(offset_end) \
00167 + MostSignificantBitPosition##size(active_range); \
00168 } else { \
00169 return -1; \
00170 } \
00171 } else { \
00172 const uint##size end_mask = \
00173 bits[offset_end] & IntervalDown##size(pos_end); \
00174 if (end_mask) { \
00175 return BitShift##size(offset_end) \
00176 + MostSignificantBitPosition##size(end_mask); \
00177 } else { \
00178 for (int offset = offset_end - 1; \
00179 offset > offset_start; \
00180 --offset) { \
00181 if (bits[offset]) { \
00182 return BitShift##size(offset) \
00183 + MostSignificantBitPosition##size(bits[offset]); \
00184 } \
00185 } \
00186 const int pos_start = BitPos##size(start); \
00187 const uint##size active_range = \
00188 bits[offset_start] & IntervalUp##size(pos_start); \
00189 if (active_range) { \
00190 return BitShift##size(offset_start) \
00191 + MostSignificantBitPosition##size(active_range); \
00192 } else { \
00193 return -1; \
00194 } \
00195 } \
00196 } \
00197 }
00198
00199 MOST_SIGNIFICANT_BIT_POSITION(64)
00200 MOST_SIGNIFICANT_BIT_POSITION(32)
00201
00202 #undef MOST_SIGNIFICANT_BIT_POSITION
00203
00204 #define UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION(size) \
00205 int##size UnsafeLeastSignificantBitPosition##size( \
00206 const uint##size* const bits, uint##size start, uint##size end) { \
00207 DCHECK_LE(start, end); \
00208 DCHECK(IsBitSet##size(bits, end)); \
00209 if (IsBitSet##size(bits, start)) { \
00210 return start; \
00211 } \
00212 const int offset_start = BitOffset##size(start); \
00213 const int offset_end = BitOffset##size(end); \
00214 const int pos_start = BitPos##size(start); \
00215 const uint##size start_mask = \
00216 bits[offset_start] & IntervalUp##size(pos_start); \
00217 if (start_mask) { \
00218 return BitShift##size(offset_start) \
00219 + LeastSignificantBitPosition##size(start_mask); \
00220 } \
00221 for (int offset = offset_start + 1; \
00222 offset <= offset_end; \
00223 ++offset) { \
00224 if (bits[offset]) { \
00225 return BitShift##size(offset) \
00226 + LeastSignificantBitPosition##size(bits[offset]); \
00227 } \
00228 } \
00229 return -1; \
00230 }
00231
00232 UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION(64)
00233 UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION(32)
00234
00235 #undef UNSAFE_LEAST_SIGNIFICANT_BIT_POSITION
00236
00237 #define UNSAFE_MOST_SIGNIFICANT_BIT_POSITION(size) \
00238 int##size UnsafeMostSignificantBitPosition##size( \
00239 const uint##size* const bits, uint##size start, uint##size end) { \
00240 DCHECK_GE(end, start); \
00241 DCHECK(IsBitSet##size(bits, start)); \
00242 if (IsBitSet##size(bits, end)) { \
00243 return end; \
00244 } \
00245 const int offset_start = BitOffset##size(start); \
00246 const int offset_end = BitOffset##size(end); \
00247 const int pos_end = BitPos##size(end); \
00248 const uint##size end_mask = \
00249 bits[offset_end] & IntervalDown##size(pos_end); \
00250 if (end_mask) { \
00251 return BitShift##size(offset_end) \
00252 + MostSignificantBitPosition##size(end_mask); \
00253 } \
00254 for (int offset = offset_end - 1; \
00255 offset >= offset_start; \
00256 --offset) { \
00257 if (bits[offset]) { \
00258 return BitShift##size(offset) \
00259 + MostSignificantBitPosition##size(bits[offset]); \
00260 } \
00261 } \
00262 return -1; \
00263 }
00264
00265 UNSAFE_MOST_SIGNIFICANT_BIT_POSITION(64)
00266 UNSAFE_MOST_SIGNIFICANT_BIT_POSITION(32)
00267
00268 #undef UNSAFE_MOST_SIGNIFICANT_BIT_POSITION
00269
00270 }