Skip to content

Commit 91f8274

Browse files
committed
BitSet to have a non-bitarray backed interface (eg. compressed structures)
1 parent 2e39b1f commit 91f8274

File tree

8 files changed

+460
-38
lines changed

8 files changed

+460
-38
lines changed

CHANGELOG.md

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

33
- `asUint64Iterable()` added to provide interface-level compatibility for future compressed bit arrays.
4+
- `BitSet` to have a non-bitarray backed interface (eg. compressed structures).
45

56
## 1.0.0
67

lib/bit_array.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ import 'dart:typed_data';
66

77
part 'src/bit_array.dart';
88
part 'src/bit_counter.dart';
9+
part 'src/bit_set.dart';

lib/src/bit_array.dart

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
part of bit_array;
22

33
/// Bit array to store bits.
4-
class BitArray {
4+
class BitArray implements BitSet {
55
Uint64List _data;
66
int _length;
77

@@ -19,7 +19,17 @@ class BitArray {
1919
return new BitArray._(data);
2020
}
2121

22+
/// Creates a bit array using a generic bit set.
23+
factory BitArray.fromBitSet(BitSet set, {int length}) {
24+
length ??= set.length;
25+
final setDataLength = _bufferLength64(set.length);
26+
final data = new Uint64List(_bufferLength64(length));
27+
data.setRange(0, setDataLength, set.asUint64Iterable());
28+
return new BitArray._(data);
29+
}
30+
2231
/// The value of the bit with the specified [index].
32+
@override
2333
bool operator [](int index) {
2434
return (_data[index >> 6] & _bitMask[index & 0x3f]) != 0;
2535
}
@@ -50,6 +60,7 @@ class BitArray {
5060
}
5161

5262
/// The number of bits set to true.
63+
@override
5364
int get cardinality => _data.buffer
5465
.asUint8List()
5566
.fold(0, (sum, value) => sum + _cardinalityBitCounts[value]);
@@ -106,70 +117,76 @@ class BitArray {
106117
}
107118

108119
/// Update the current [BitArray] using a logical AND operation with the
109-
/// corresponding elements in the specified [array].
110-
/// Excess size of the [array] is ignored.
111-
void and(BitArray array) {
112-
final minLength = math.min(_data.length, array._data.length);
113-
for (int i = 0; i < minLength; i++) {
114-
_data[i] &= array._data[i];
120+
/// corresponding elements in the specified [set].
121+
/// Excess size of the [set] is ignored.
122+
void and(BitSet set) {
123+
final iter = set.asUint64Iterable().iterator;
124+
int i = 0;
125+
for (; i < _data.length && iter.moveNext(); i++) {
126+
_data[i] &= iter.current;
115127
}
116-
for (int i = minLength; i < _data.length; i++) {
128+
for (; i < _data.length; i++) {
117129
_data[i] = 0;
118130
}
119131
}
120132

121133
/// Update the current [BitArray] using a logical AND NOT operation with the
122-
/// corresponding elements in the specified [array].
123-
/// Excess size of the [array] is ignored.
124-
void andNot(BitArray array) {
125-
final minLength = math.min(_data.length, array._data.length);
126-
for (int i = 0; i < minLength; i++) {
127-
_data[i] &= ~array._data[i];
134+
/// corresponding elements in the specified [set].
135+
/// Excess size of the [set] is ignored.
136+
void andNot(BitSet set) {
137+
final iter = set.asUint64Iterable().iterator;
138+
for (int i = 0; i < _data.length && iter.moveNext(); i++) {
139+
_data[i] &= ~iter.current;
128140
}
129141
}
130142

131143
/// Update the current [BitArray] using a logical OR operation with the
132-
/// corresponding elements in the specified [array].
133-
/// Excess size of the [array] is ignored.
134-
void or(BitArray array) {
135-
final minLength = math.min(_data.length, array._data.length);
136-
for (int i = 0; i < minLength; i++) {
137-
_data[i] |= array._data[i];
144+
/// corresponding elements in the specified [set].
145+
/// Excess size of the [set] is ignored.
146+
void or(BitSet set) {
147+
final iter = set.asUint64Iterable().iterator;
148+
for (int i = 0; i < _data.length && iter.moveNext(); i++) {
149+
_data[i] |= iter.current;
138150
}
139151
}
140152

141153
/// Update the current [BitArray] using a logical XOR operation with the
142-
/// corresponding elements in the specified [array].
143-
/// Excess size of the [array] is ignored.
144-
void xor(BitArray array) {
145-
final minLength = math.min(_data.length, array._data.length);
146-
for (int i = 0; i < minLength; i++) {
147-
_data[i] = _data[i] ^ array._data[i];
154+
/// corresponding elements in the specified [set].
155+
/// Excess size of the [set] is ignored.
156+
void xor(BitSet set) {
157+
final iter = set.asUint64Iterable().iterator;
158+
for (int i = 0; i < _data.length && iter.moveNext(); i++) {
159+
_data[i] = _data[i] ^ iter.current;
148160
}
149161
}
150162

151163
/// Creates a copy of the current [BitArray].
164+
@override
152165
BitArray clone() {
153166
final newData = new Uint64List(_data.length);
154167
newData.setRange(0, _data.length, _data);
155168
return new BitArray._(newData);
156169
}
157170

158171
/// Creates a new [BitArray] using a logical AND operation with the
159-
/// corresponding elements in the specified [array].
160-
BitArray operator &(BitArray array) => clone()..and(array);
172+
/// corresponding elements in the specified [set].
173+
/// Excess size of the [set] is ignored.
174+
BitArray operator &(BitSet set) => clone()..and(set);
161175

162176
/// Creates a new [BitArray] using a logical AND NOT operation with the
163-
/// corresponding elements in the specified [array].
164-
BitArray operator %(BitArray array) => clone()..andNot(array);
177+
/// corresponding elements in the specified [set].
178+
/// Excess size of the [set] is ignored.
179+
BitArray operator %(BitSet set) => clone()..andNot(set);
165180

166181
/// Creates a new [BitArray] using a logical OR operation with the
167-
/// corresponding elements in the specified [array].
168-
BitArray operator |(BitArray array) => clone()..or(array);
182+
/// corresponding elements in the specified [set].
183+
/// Excess size of the [set] is ignored.
184+
BitArray operator |(BitSet set) => clone()..or(set);
169185

170186
/// Creates a new [BitArray] using a logical XOR operation with the
171-
/// corresponding elements in the specified [array].
172-
BitArray operator ^(BitArray array) => clone()..xor(array);
187+
/// corresponding elements in the specified [set].
188+
/// Excess size of the [set] is ignored.
189+
BitArray operator ^(BitSet set) => clone()..xor(set);
173190

174191
/// Creates a string of 0s and 1s of the content of the array.
175192
String toBinaryString() {
@@ -186,10 +203,12 @@ class BitArray {
186203

187204
/// Returns an iterable wrapper of the bit array that iterates over the index
188205
/// numbers and returns the 64-bit int blocks.
206+
@override
189207
Iterable<int> asUint64Iterable() => _data;
190208

191209
/// Returns an iterable wrapper of the bit array that iterates over the index
192210
/// numbers that match [value] (by default the bits that are set).
211+
@override
193212
Iterable<int> asIntIterable([bool value = true]) {
194213
return new _IntIterable(this, value);
195214
}

lib/src/bit_counter.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ class BitCounter {
5959

6060
/// Adds a bit [array] to the counter.
6161
void addBitArray(BitArray array) {
62-
if (_length < array.length) {
63-
_length = array.length;
62+
addBitSet(array);
63+
}
64+
65+
/// Adds a [set] to the counter.
66+
void addBitSet(BitSet set) {
67+
if (_length < set.length) {
68+
_length = set.length;
6469
_bits.forEach((a) => a.length = _length);
6570
}
66-
final arrayDataLength = _length >> 6;
67-
final iterator = array.asUint64Iterable().iterator;
71+
final arrayDataLength = _bufferLength64(_length);
72+
final iterator = set.asUint64Iterable().iterator;
6873
for (int i = 0; i < arrayDataLength && iterator.moveNext(); i++) {
6974
int overflow = iterator.current;
7075

0 commit comments

Comments
 (0)