Repository navigation
Expand file tree
/
Copy pathBitArray32.js
More file actions
141 lines (124 loc) · 4.89 KB
/
Copy pathBitArray32.js
File metadata and controls
141 lines (124 loc) · 4.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
export default class BitArray32 extends DataView {
constructor(sizeOrBuffer) {
let len = 0;
if (sizeOrBuffer instanceof ArrayBuffer) {
len = sizeOrBuffer.byteLength * 8;
super(sizeOrBuffer);
} else if (Number.isInteger(sizeOrBuffer)) {
if (sizeOrBuffer > 0x03ff000000) { throw new Error("BitArray size can not exceed 17163091968"); }
super(new ArrayBuffer(Number((BigInt(sizeOrBuffer + 31) & ~31n) >> 3n))); // Sets ArrayBuffer.byteLength to multiples of 4 bytes (32 bits)));
len = this.buffer.byteLength * 8;
} else {
throw new Error("An integer size or buffer must be provided when initalizing a BitArray");
}
Object.defineProperty( this
, "length"
, { configurable: false
, enumerable : false
, writable : false
, value : len
}
);
}
get popcount(){
let m1 = 0x55555555;
let m2 = 0x33333333;
let m4 = 0x0f0f0f0f;
let h01 = 0x01010101;
let pc = 0;
let x;
for (let i = 0; i < this.buffer.byteLength; i++){
x = this.getUint8(i);
x -= (x >> 1) & m1; //put count of each 2 bits into those 2 bits
x = (x & m2) + ((x >> 2) & m2); //put count of each 4 bits into those 4 bits
x = (x + (x >> 4)) & m4; //put count of each 8 bits into those 8 bits
pc += (x * h01) >> 56;
}
return pc;
}
and(bar, inPlace = false){
// And of this and bar. Example: 1100 & 1001 = 1000
let len = Math.min(this.buffer.byteLength,bar.buffer.byteLength),
res = inPlace ? this : new BitArray32(len * 8);
for (var i = 0; i < len; i += 4) res.setUint32(i,this.getUint32(i) & bar.getUint32(i));
return res;
}
any(){
// Returns true if any of the bits in the BitArray are set. If returns false then all bits are 0
let len = this.buffer.byteLength,
res = true;
for (var i = 0; res && i < len; i += 4) res = this.getUint32(i) === 0;
return !res;
}
at(i){
// Fetches the value at the given index
return this.getUint8(i / 8) & (1 << (i & 7)) ? 1 : 0;
}
clear(){
// Resets the BitArray in place
for (let i = 0, len = this.buffer.byteLength; i < len; i += 4) this.setUint32(i,0);
}
every(){
// Returns true if all bits in the BitArray are set.
let len = this.buffer.byteLength,
res = true;
for (var i = 0; res && i < len; i += 4) res = this.getUint32(i) === 0xffffffff;
return res;
}
fill(){
// Sets the BitArray in place
for (let i = 0, len = this.buffer.byteLength; i < len; i += 4) this.setUint32(i,0xffffffff);
}
not(inPlace = false){
// Flips all the bits in this buffer. Example: 1100 = 0011
let len = this.buffer.byteLength,
res = inPlace ? this : new BitArray32(len * 8);
for (var i = 0; i < len; i += 4) res.setUint32(i,~(this.getUint32(i) >>> 0));
return res;
}
or(bar, inPlace = false){
// Or of this and bar. Example: 1100 & 1001 = 1101
let len = Math.min(this.buffer.byteLength,bar.buffer.byteLength),
res = inPlace ? this : new BitArray32(len * 8);
for (var i = 0; i < len; i += 4) res.setUint32(i,this.getUint32(i) | bar.getUint32(i));
return res;
}
reset(i){
// Resets the value at the given index.
this.setUint8(i / 8, this.getUint8(i / 8) & ~(1 << (i & 7)));
}
set(i){
// Sets the value at the given index.
this.setUint8(i / 8, this.getUint8(i / 8) | (1 << (i & 7)));
}
slice(a = 0, b = this.buffer.byteLength){
// Slices BitArray and returns a new BitArray with buffer byteLength in multiples of 4 bytes (32 bits)
// The default argument values instantiate a clone.
b = a + Number((BigInt(b - a + 31) & ~31n));
return new BitArray32(this.buffer.slice(a, b));
}
toggle(i){
// Flips the value at the given index
this.setUint8(i / 8, this.getUint8(i / 8) ^ (1 << (n & 7)));
}
// For efficiency maps this.buffer to an Uint8Array and byte by byte reverses the rank of bits and stringifies by
// reducing. However stringifying a huge BitArray is meaningless. Perhaps limiting the string size to 128 is reasonable.
toString(){
return new Uint8Array(this.buffer).reduce((p,c) => p + ((BigInt(c)* 0x0202020202n & 0x010884422010n) % 1023n).toString(2).padStart(8,"0"),"");
}
xor(bar, inPlace = false){
// Xor of this and bar. Example: 1100 & 1001 = 0101;
let len = Math.min(this.buffer.byteLength,bar.buffer.byteLength),
res = inPlace ? this : new BitArray32(len * 8);
for (var i = 0; i < len; i += 4) res.setUint32(i,this.getUint32(i) ^ bar.getUint32(i));
return res;
}
clone() {
// Copies the values from this BitArray into a new BitArray
let result = new BitArray32(this.buffer.byteLength);
for (let i = 0; i < this.buffer.byteLength/8; i++) {
result.setUint32(i, this.getUint32(i));
}
return result;
}
}