@@ -410,6 +410,9 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> {
410
410
/// some stretches with lots of 0s and 1s mixed in a way that causes trouble
411
411
/// for `IntervalSet`.
412
412
///
413
+ /// Best used via `MixedBitSet`, rather than directly, because `MixedBitSet`
414
+ /// has better performance for small bitsets.
415
+ ///
413
416
/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
414
417
/// just be `usize`.
415
418
///
@@ -1106,6 +1109,160 @@ where
1106
1109
false
1107
1110
}
1108
1111
1112
+ /// A bitset with a mixed representation, using `BitSet` for small and medium
1113
+ /// bitsets, and `ChunkedBitSet` for large bitsets, i.e. those with enough bits
1114
+ /// for at least two chunks. This is a good choice for many bitsets that can
1115
+ /// have large domain sizes (e.g. 5000+).
1116
+ ///
1117
+ /// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
1118
+ /// just be `usize`.
1119
+ ///
1120
+ /// All operations that involve an element will panic if the element is equal
1121
+ /// to or greater than the domain size. All operations that involve two bitsets
1122
+ /// will panic if the bitsets have differing domain sizes.
1123
+ #[ derive( PartialEq , Eq ) ]
1124
+ pub enum MixedBitSet < T > {
1125
+ Small ( BitSet < T > ) ,
1126
+ Large ( ChunkedBitSet < T > ) ,
1127
+ }
1128
+
1129
+ impl < T > MixedBitSet < T > {
1130
+ /// Gets the domain size.
1131
+ pub fn domain_size ( & self ) -> usize {
1132
+ match self {
1133
+ MixedBitSet :: Small ( set) => set. domain_size ( ) ,
1134
+ MixedBitSet :: Large ( set) => set. domain_size ( ) ,
1135
+ }
1136
+ }
1137
+ }
1138
+
1139
+ impl < T : Idx > MixedBitSet < T > {
1140
+ /// Creates a new, empty bitset with a given `domain_size`.
1141
+ #[ inline]
1142
+ pub fn new_empty ( domain_size : usize ) -> MixedBitSet < T > {
1143
+ if domain_size <= CHUNK_BITS {
1144
+ MixedBitSet :: Small ( BitSet :: new_empty ( domain_size) )
1145
+ } else {
1146
+ MixedBitSet :: Large ( ChunkedBitSet :: new_empty ( domain_size) )
1147
+ }
1148
+ }
1149
+
1150
+ #[ inline]
1151
+ pub fn is_empty ( & self ) -> bool {
1152
+ match self {
1153
+ MixedBitSet :: Small ( set) => set. is_empty ( ) ,
1154
+ MixedBitSet :: Large ( set) => set. is_empty ( ) ,
1155
+ }
1156
+ }
1157
+
1158
+ #[ inline]
1159
+ pub fn contains ( & self , elem : T ) -> bool {
1160
+ match self {
1161
+ MixedBitSet :: Small ( set) => set. contains ( elem) ,
1162
+ MixedBitSet :: Large ( set) => set. contains ( elem) ,
1163
+ }
1164
+ }
1165
+
1166
+ #[ inline]
1167
+ pub fn insert ( & mut self , elem : T ) -> bool {
1168
+ match self {
1169
+ MixedBitSet :: Small ( set) => set. insert ( elem) ,
1170
+ MixedBitSet :: Large ( set) => set. insert ( elem) ,
1171
+ }
1172
+ }
1173
+
1174
+ pub fn insert_all ( & mut self ) {
1175
+ match self {
1176
+ MixedBitSet :: Small ( set) => set. insert_all ( ) ,
1177
+ MixedBitSet :: Large ( set) => set. insert_all ( ) ,
1178
+ }
1179
+ }
1180
+
1181
+ #[ inline]
1182
+ pub fn remove ( & mut self , elem : T ) -> bool {
1183
+ match self {
1184
+ MixedBitSet :: Small ( set) => set. remove ( elem) ,
1185
+ MixedBitSet :: Large ( set) => set. remove ( elem) ,
1186
+ }
1187
+ }
1188
+
1189
+ pub fn iter ( & self ) -> MixedBitIter < ' _ , T > {
1190
+ match self {
1191
+ MixedBitSet :: Small ( set) => MixedBitIter :: Small ( set. iter ( ) ) ,
1192
+ MixedBitSet :: Large ( set) => MixedBitIter :: Large ( set. iter ( ) ) ,
1193
+ }
1194
+ }
1195
+
1196
+ bit_relations_inherent_impls ! { }
1197
+ }
1198
+
1199
+ impl < T > Clone for MixedBitSet < T > {
1200
+ fn clone ( & self ) -> Self {
1201
+ match self {
1202
+ MixedBitSet :: Small ( set) => MixedBitSet :: Small ( set. clone ( ) ) ,
1203
+ MixedBitSet :: Large ( set) => MixedBitSet :: Large ( set. clone ( ) ) ,
1204
+ }
1205
+ }
1206
+
1207
+ /// WARNING: this implementation of clone_from may panic if the two
1208
+ /// bitsets have different domain sizes. This constraint is not inherent to
1209
+ /// `clone_from`, but it works with the existing call sites and allows a
1210
+ /// faster implementation, which is important because this function is hot.
1211
+ fn clone_from ( & mut self , from : & Self ) {
1212
+ match ( self , from) {
1213
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( from) ) => set. clone_from ( from) ,
1214
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( from) ) => set. clone_from ( from) ,
1215
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1216
+ }
1217
+ }
1218
+ }
1219
+
1220
+ impl < T : Idx > BitRelations < MixedBitSet < T > > for MixedBitSet < T > {
1221
+ fn union ( & mut self , other : & MixedBitSet < T > ) -> bool {
1222
+ match ( self , other) {
1223
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( other) ) => set. union ( other) ,
1224
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( other) ) => set. union ( other) ,
1225
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1226
+ }
1227
+ }
1228
+
1229
+ fn subtract ( & mut self , other : & MixedBitSet < T > ) -> bool {
1230
+ match ( self , other) {
1231
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( other) ) => set. subtract ( other) ,
1232
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( other) ) => set. subtract ( other) ,
1233
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1234
+ }
1235
+ }
1236
+
1237
+ fn intersect ( & mut self , _other : & MixedBitSet < T > ) -> bool {
1238
+ unimplemented ! ( "implement if/when necessary" ) ;
1239
+ }
1240
+ }
1241
+
1242
+ impl < T : Idx > fmt:: Debug for MixedBitSet < T > {
1243
+ fn fmt ( & self , w : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1244
+ match self {
1245
+ MixedBitSet :: Small ( set) => set. fmt ( w) ,
1246
+ MixedBitSet :: Large ( set) => set. fmt ( w) ,
1247
+ }
1248
+ }
1249
+ }
1250
+
1251
+ pub enum MixedBitIter < ' a , T : Idx > {
1252
+ Small ( BitIter < ' a , T > ) ,
1253
+ Large ( ChunkedBitIter < ' a , T > ) ,
1254
+ }
1255
+
1256
+ impl < ' a , T : Idx > Iterator for MixedBitIter < ' a , T > {
1257
+ type Item = T ;
1258
+ fn next ( & mut self ) -> Option < T > {
1259
+ match self {
1260
+ MixedBitIter :: Small ( iter) => iter. next ( ) ,
1261
+ MixedBitIter :: Large ( iter) => iter. next ( ) ,
1262
+ }
1263
+ }
1264
+ }
1265
+
1109
1266
/// A resizable bitset type with a dense representation.
1110
1267
///
1111
1268
/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
0 commit comments