@@ -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,158 @@ 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
+ pub fn domain_size ( & self ) -> usize {
1131
+ match self {
1132
+ MixedBitSet :: Small ( set) => set. domain_size ( ) ,
1133
+ MixedBitSet :: Large ( set) => set. domain_size ( ) ,
1134
+ }
1135
+ }
1136
+ }
1137
+
1138
+ impl < T : Idx > MixedBitSet < T > {
1139
+ #[ inline]
1140
+ pub fn new_empty ( domain_size : usize ) -> MixedBitSet < T > {
1141
+ if domain_size <= CHUNK_BITS {
1142
+ MixedBitSet :: Small ( BitSet :: new_empty ( domain_size) )
1143
+ } else {
1144
+ MixedBitSet :: Large ( ChunkedBitSet :: new_empty ( domain_size) )
1145
+ }
1146
+ }
1147
+
1148
+ #[ inline]
1149
+ pub fn is_empty ( & self ) -> bool {
1150
+ match self {
1151
+ MixedBitSet :: Small ( set) => set. is_empty ( ) ,
1152
+ MixedBitSet :: Large ( set) => set. is_empty ( ) ,
1153
+ }
1154
+ }
1155
+
1156
+ #[ inline]
1157
+ pub fn contains ( & self , elem : T ) -> bool {
1158
+ match self {
1159
+ MixedBitSet :: Small ( set) => set. contains ( elem) ,
1160
+ MixedBitSet :: Large ( set) => set. contains ( elem) ,
1161
+ }
1162
+ }
1163
+
1164
+ #[ inline]
1165
+ pub fn insert ( & mut self , elem : T ) -> bool {
1166
+ match self {
1167
+ MixedBitSet :: Small ( set) => set. insert ( elem) ,
1168
+ MixedBitSet :: Large ( set) => set. insert ( elem) ,
1169
+ }
1170
+ }
1171
+
1172
+ pub fn insert_all ( & mut self ) {
1173
+ match self {
1174
+ MixedBitSet :: Small ( set) => set. insert_all ( ) ,
1175
+ MixedBitSet :: Large ( set) => set. insert_all ( ) ,
1176
+ }
1177
+ }
1178
+
1179
+ #[ inline]
1180
+ pub fn remove ( & mut self , elem : T ) -> bool {
1181
+ match self {
1182
+ MixedBitSet :: Small ( set) => set. remove ( elem) ,
1183
+ MixedBitSet :: Large ( set) => set. remove ( elem) ,
1184
+ }
1185
+ }
1186
+
1187
+ pub fn iter ( & self ) -> MixedBitIter < ' _ , T > {
1188
+ match self {
1189
+ MixedBitSet :: Small ( set) => MixedBitIter :: Small ( set. iter ( ) ) ,
1190
+ MixedBitSet :: Large ( set) => MixedBitIter :: Large ( set. iter ( ) ) ,
1191
+ }
1192
+ }
1193
+
1194
+ bit_relations_inherent_impls ! { }
1195
+ }
1196
+
1197
+ impl < T > Clone for MixedBitSet < T > {
1198
+ fn clone ( & self ) -> Self {
1199
+ match self {
1200
+ MixedBitSet :: Small ( set) => MixedBitSet :: Small ( set. clone ( ) ) ,
1201
+ MixedBitSet :: Large ( set) => MixedBitSet :: Large ( set. clone ( ) ) ,
1202
+ }
1203
+ }
1204
+
1205
+ /// WARNING: this implementation of clone_from may panic if the two
1206
+ /// bitsets have different domain sizes. This constraint is not inherent to
1207
+ /// `clone_from`, but it works with the existing call sites and allows a
1208
+ /// faster implementation, which is important because this function is hot.
1209
+ fn clone_from ( & mut self , from : & Self ) {
1210
+ match ( self , from) {
1211
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( from) ) => set. clone_from ( from) ,
1212
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( from) ) => set. clone_from ( from) ,
1213
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1214
+ }
1215
+ }
1216
+ }
1217
+
1218
+ impl < T : Idx > BitRelations < MixedBitSet < T > > for MixedBitSet < T > {
1219
+ fn union ( & mut self , other : & MixedBitSet < T > ) -> bool {
1220
+ match ( self , other) {
1221
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( other) ) => set. union ( other) ,
1222
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( other) ) => set. union ( other) ,
1223
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1224
+ }
1225
+ }
1226
+
1227
+ fn subtract ( & mut self , other : & MixedBitSet < T > ) -> bool {
1228
+ match ( self , other) {
1229
+ ( MixedBitSet :: Small ( set) , MixedBitSet :: Small ( other) ) => set. subtract ( other) ,
1230
+ ( MixedBitSet :: Large ( set) , MixedBitSet :: Large ( other) ) => set. subtract ( other) ,
1231
+ _ => panic ! ( "MixedBitSet size mismatch" ) ,
1232
+ }
1233
+ }
1234
+
1235
+ fn intersect ( & mut self , _other : & MixedBitSet < T > ) -> bool {
1236
+ unimplemented ! ( "implement if/when necessary" ) ;
1237
+ }
1238
+ }
1239
+
1240
+ impl < T : Idx > fmt:: Debug for MixedBitSet < T > {
1241
+ fn fmt ( & self , w : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1242
+ match self {
1243
+ MixedBitSet :: Small ( set) => set. fmt ( w) ,
1244
+ MixedBitSet :: Large ( set) => set. fmt ( w) ,
1245
+ }
1246
+ }
1247
+ }
1248
+
1249
+ pub enum MixedBitIter < ' a , T : Idx > {
1250
+ Small ( BitIter < ' a , T > ) ,
1251
+ Large ( ChunkedBitIter < ' a , T > ) ,
1252
+ }
1253
+
1254
+ impl < ' a , T : Idx > Iterator for MixedBitIter < ' a , T > {
1255
+ type Item = T ;
1256
+ fn next ( & mut self ) -> Option < T > {
1257
+ match self {
1258
+ MixedBitIter :: Small ( iter) => iter. next ( ) ,
1259
+ MixedBitIter :: Large ( iter) => iter. next ( ) ,
1260
+ }
1261
+ }
1262
+ }
1263
+
1109
1264
/// A resizable bitset type with a dense representation.
1110
1265
///
1111
1266
/// `T` is an index type, typically a newtyped `usize` wrapper, but it can also
0 commit comments