Skip to content

Commit 7965988

Browse files
committed
BitArray.setRange and BitArray.clearRange
1 parent 21aaacd commit 7965988

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- Updated SDK constraint, lints and format.
44
- `BitArray.setWhere` and `BitArray.clearWhere` for callback-driven updates.
5+
- `BitArray.setRange` and `BitArray.clearRange` for efficient continous-range updates.
56
- More efficient `BitArray` operations: `setAll`, `clearAll`.
67
- More efficient `BitArray` operations: `and`, `andNot`, `or`, `xor` when the parameter is another `BitArray`.
78

lib/src/bit_array.dart

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,35 @@ class BitArray extends BitSet {
143143
}
144144
}
145145

146+
/// Sets the bits from [start] (inclusive) up to [end] (exclusive) to false.
147+
void clearRange(int start, int end) {
148+
assert(start >= 0 && start < _length);
149+
assert(start <= end && end <= _length);
150+
if (start == end) return;
151+
final dataStart = start >> 5;
152+
final dataEnd = (end - 1) >> 5;
153+
final maskStart = start & 0x1f;
154+
final maskEnd = (end - 1) & 0x1f;
155+
156+
if (dataStart == dataEnd) {
157+
for (var i = maskStart; i <= maskEnd; i++) {
158+
_data[dataStart] &= _clearMask[i];
159+
}
160+
return;
161+
}
162+
if (maskStart == 0) {
163+
_data[dataStart] = 0;
164+
} else {
165+
for (var i = maskStart; i < _clearMask.length; i++) {
166+
_data[dataStart] &= _clearMask[i];
167+
}
168+
}
169+
_data.fillRange(dataStart + 1, dataEnd, 0);
170+
for (var i = 0; i <= maskEnd; i++) {
171+
_data[dataEnd] &= _clearMask[i];
172+
}
173+
}
174+
146175
/// Sets all of the bits in the current [BitArray] to false.
147176
void clearAll() {
148177
_data.fillRange(0, _data.length, 0);
@@ -180,6 +209,35 @@ class BitArray extends BitSet {
180209
}
181210
}
182211

212+
/// Sets the bits from [start] (inclusive) up to [end] (exclusive) to false.
213+
void setRange(int start, int end) {
214+
assert(start >= 0 && start < _length);
215+
assert(start <= end && end <= _length);
216+
if (start == end) return;
217+
final dataStart = start >> 5;
218+
final dataEnd = (end - 1) >> 5;
219+
final maskStart = start & 0x1f;
220+
final maskEnd = (end - 1) & 0x1f;
221+
222+
if (dataStart == dataEnd) {
223+
for (var i = maskStart; i <= maskEnd; i++) {
224+
_data[dataStart] |= _bitMask[i];
225+
}
226+
return;
227+
}
228+
if (maskStart == 0) {
229+
_data[dataStart] = -1;
230+
} else {
231+
for (var i = maskStart; i < _bitMask.length; i++) {
232+
_data[dataStart] |= _bitMask[i];
233+
}
234+
}
235+
_data.fillRange(dataStart + 1, dataEnd, -1);
236+
for (var i = 0; i <= maskEnd; i++) {
237+
_data[dataEnd] |= _bitMask[i];
238+
}
239+
}
240+
183241
/// Sets all the bit values in the current [BitArray] to true.
184242
void setAll() {
185243
_data.fillRange(0, _data.length, -1);

test/bit_array_test.dart

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,45 @@ void main() {
188188
}
189189
}
190190
});
191+
192+
test('clearRange', () {
193+
for (var start = 0; start < 128; start++) {
194+
for (var end = start; end <= 128; end++) {
195+
final array = BitArray(128);
196+
array.clearRange(start, end);
197+
expect(array.cardinality, 0);
198+
array.setAll();
199+
array.clearRange(start, end);
200+
for (var i = 0; i < 128; i++) {
201+
expect(
202+
array[i],
203+
i < start || i >= end,
204+
reason: '$start-$end $i ${array[i]}',
205+
);
206+
}
207+
}
208+
}
209+
});
210+
211+
test('setRange', () {
212+
for (var start = 0; start < 128; start++) {
213+
for (var end = start; end <= 128; end++) {
214+
final array = BitArray(128);
215+
array.setAll();
216+
array.setRange(start, end);
217+
expect(array.cardinality, 128);
218+
array.clearAll();
219+
array.setRange(start, end);
220+
for (var i = 0; i < 128; i++) {
221+
expect(
222+
array[i],
223+
i >= start && i < end,
224+
reason: '$start-$end $i ${array[i]}',
225+
);
226+
}
227+
}
228+
}
229+
});
191230
});
192231

193232
group('BitArray equals and hashCode', () {

0 commit comments

Comments
 (0)