-
-
Notifications
You must be signed in to change notification settings - Fork 60
Expand file tree
/
Copy pathbitset.gd
More file actions
95 lines (73 loc) · 2.32 KB
/
bitset.gd
File metadata and controls
95 lines (73 loc) · 2.32 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
extends RefCounted
class_name _Bitset
# Stores a list of booleans, representing them efficiently as a PackedByteArray
var _data: PackedByteArray
var _bit_count: int
static func of_bools(values: Array) -> _Bitset:
var result := _Bitset.new(values.size())
for i in values.size():
if values[i]:
result.set_bit(i)
return result
func _init(bit_count: int):
var bytes := bit_count / 8
if bit_count % 8 > 0:
bytes += 1
_data = PackedByteArray()
_data.resize(bytes)
_bit_count = bit_count
func bit_count() -> int:
return _bit_count
func is_empty() -> bool:
return _bit_count == 0
func is_not_empty() -> bool:
return _bit_count != 0
func get_bit(idx: int) -> bool:
assert(idx < _bit_count, "Accessing bit %d on bitset of size %d!" % [idx, _bit_count])
var byte_idx := idx / 8
var bit_idx := idx % 8
return (_data[byte_idx] >> bit_idx) & 0x1 != 0
func set_bit(idx: int) -> void:
assert(idx < _bit_count, "Accessing bit %d on bitset of size %d!" % [idx, _bit_count])
var byte_idx := idx / 8
var bit_idx := idx % 8
_data[byte_idx] |= 0x1 << bit_idx
func clear_bit(idx: int) -> void:
assert(idx < _bit_count, "Accessing bit %d on bitset of size %d!" % [idx, _bit_count])
var byte_idx := idx / 8
var bit_idx := idx % 8
_data[byte_idx] &= ~(0x1 << bit_idx)
func toggle_bit(idx: int) -> void:
assert(idx < _bit_count, "Accessing bit %d on bitset of size %d!" % [idx, _bit_count])
var byte_idx := idx / 8
var bit_idx := idx % 8
_data[byte_idx] ^= 0x1 << bit_idx
func get_set_indices() -> Array[int]:
var result := [] as Array[int]
for i in _data.size():
var byte := _data[i]
if byte & 0x01: result.append(i * 8 + 0)
if byte & 0x02: result.append(i * 8 + 1)
if byte & 0x04: result.append(i * 8 + 2)
if byte & 0x08: result.append(i * 8 + 3)
if byte & 0x10: result.append(i * 8 + 4)
if byte & 0x20: result.append(i * 8 + 5)
if byte & 0x40: result.append(i * 8 + 6)
if byte & 0x80: result.append(i * 8 + 7)
return result
func equals(other) -> bool:
if other is _Bitset:
return other._bit_count == _bit_count and other._data == _data
else:
return false
func _to_string() -> String:
if is_empty():
return "Bitset(n=0)"
else:
var body := ""
for i in _bit_count:
if i != 0 and i % 4 == 0:
body += " "
if get_bit(i): body += "1"
else: body += "0"
return "Bitset(n=%d, %s)" % [_bit_count, body]