forked from TimvanScherpenzeel/spars
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBitfield.ts
More file actions
90 lines (79 loc) · 2.28 KB
/
Bitfield.ts
File metadata and controls
90 lines (79 loc) · 2.28 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
/**
* Inspired by https://github.com/thi-ng/umbrella/blob/master/packages/bitfield/src/bitfield.ts
*/
/**
* BitField is a simple resizable bitfield data structure
* It is an efficient way of storing many boolean values
*/
export class BitField {
private data: Uint32Array;
private size: number;
/**
* Get the current length of the bitfield
*/
get length(): number /* O(1) */ {
return this.size;
}
/**
* Set the size of the bitfield and initializes the internal data buffer
*
* @param size Size of the bitfield
*/
constructor(size: number) /* O(1) */ {
this.size = (size + 31) & ~31;
this.data = new Uint32Array(this.size >>> 5);
}
/**
* Get a bit value by index (positive number)
*
* @param index Index of bit
*/
public get(index: number): boolean /* O(1) */ {
return (this.data[index >>> 5] & (0x80000000 >>> (index & 31))) !== 0;
}
/**
* Set a bit index with value (positive number)
*
* 1 << 0 = 1 = 0b00000000000000000000000000000001
* 1 << 1 = 2 = 0b00000000000000000000000000000010
* ...... = ......... = ..................................
* 1 << 30 = 1073741824 = 0b01000000000000000000000000000000
* 1 << 31 = 2147483648 = 0b10000000000000000000000000000000
*
* Where 0, 1, ..., 30 and 31 are indices into the bitfield
*
* @param index Index of bit
* @param value Value of bit
*/
public set(index: number, value: boolean = true): boolean /* O(1) */ {
const bitIndex = index >>> 5;
const bitMask = 0x80000000 >>> (index & 31);
const bitValue = this.data[bitIndex] & bitMask;
if (value) {
this.data[bitIndex] |= bitMask;
} else {
this.data[bitIndex] &= ~bitMask;
}
return bitValue !== 0;
}
/**
* Resize the bitfield
*
* @param size New size of the bitfield
*/
public resize(size: number): void /* O(1) */ {
size = (size + 31) & ~31;
const tmp = new Uint32Array(size >>> 5);
tmp.set(this.data.slice(0, tmp.length));
this.data = tmp;
this.size = size;
}
/**
* Get the bitfield as a string representation
*/
public toString(): string /* O(n) */ {
return `0b${[...Array.from(this.data)]
.map(bit => (bit >>> 0).toString(2).padStart(32, '0'))
.join('')}`;
}
}