bitary 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -9
- data/lib/bitary/version.rb +2 -2
- data/lib/bitary.rb +125 -127
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee481b52a264fe1e578b65f0228e9a9c6e4eb57a7fa7fb224fb4c1dd31d60f0c
|
4
|
+
data.tar.gz: 2529e365b65266446aace9bce47369f49615869c4c4ab6ffe134b90c61422535
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b549423b7cbe533c07fc54b5a4f938612889508703530336b048206f4681356fbbcb04065b7d04a887ed3f03db6ad6cb94538a4b047a6e2e7eeb4904d0af5f9
|
7
|
+
data.tar.gz: 4e4831d9dcb860c06067ca92e63b41d81ac90e0d3e7aa2f0ddfd48f80f8b8352bf77c6cedbc8b5002285d29f2c6c33b9e96b1456175b1a7ebb41a272a015ce87
|
data/README.md
CHANGED
@@ -24,10 +24,8 @@ Documentation still needs to be written, but here is a breakdown
|
|
24
24
|
of the main capabilities brought by the current bit array implementation:
|
25
25
|
|
26
26
|
```ruby
|
27
|
-
|
28
|
-
|
29
|
-
bit_array_sz = BitArray.new(128) # give an explicit size. Defaults to 64 bits used per item
|
30
|
-
bit_array_ar = BitArray.new(
|
27
|
+
bit_array_sz = Bitary.new(128) # give an explicit size. Defaults to 64 bits used per item
|
28
|
+
bit_array_ar = Bitary.new(
|
31
29
|
[255, 10, 20],
|
32
30
|
bits_per_item: 8
|
33
31
|
) # create based on some integer array
|
@@ -53,18 +51,18 @@ bit_array_sz.each_byte do |byte|
|
|
53
51
|
end
|
54
52
|
|
55
53
|
# convert
|
56
|
-
bit_array_ar.to_a # [
|
57
|
-
bit_array_ar.to_s # "
|
54
|
+
bit_array_ar.to_a # [127, 10, 20]
|
55
|
+
bit_array_ar.to_s # "01111111 00001010 00010100"
|
58
56
|
|
59
57
|
# increase/decrease bits used per item
|
60
58
|
bit_array_ar.bits_per_item = 64
|
61
|
-
bit_array_ar.to_a # [
|
62
|
-
bit_array_ar.to_s # "
|
59
|
+
bit_array_ar.to_a # [8_325_652]
|
60
|
+
bit_array_ar.to_s # "0000000000000000000000000000000000000000011111110000101000010100"
|
63
61
|
|
64
62
|
bit_array_sz.bits_per_item # 64
|
65
63
|
bit_array_sz.to_a # [1_099_511_627_776, 0]
|
66
64
|
bit_array_sz.bits_per_item = 32
|
67
|
-
bit_array_sz.to_a # [256, 0, 0,
|
65
|
+
bit_array_sz.to_a # [256, 0, 0, 0]
|
68
66
|
```
|
69
67
|
|
70
68
|
## Development
|
data/lib/bitary/version.rb
CHANGED
data/lib/bitary.rb
CHANGED
@@ -2,170 +2,168 @@
|
|
2
2
|
|
3
3
|
require_relative 'bitary/version'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
attr_reader :size, :bits_per_item
|
5
|
+
class Bitary
|
6
|
+
attr_reader :size, :bits_per_item
|
8
7
|
|
9
|
-
|
10
|
-
|
8
|
+
def initialize(initial_data, bits_per_item: 64)
|
9
|
+
raise ArgumentError unless [8, 16, 32, 64].include?(bits_per_item)
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def [](index)
|
18
|
-
raise IndexError if index.negative? || index >= @size
|
11
|
+
@size = init_size(initial_data, bits_per_item)
|
12
|
+
@internal_array = init_internal_array(initial_data, @size, bits_per_item)
|
13
|
+
@bits_per_item = bits_per_item
|
14
|
+
end
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
offset = compute_relative_offset(index, item_bit_size)
|
16
|
+
def [](index)
|
17
|
+
raise IndexError if index.negative? || index >= @size
|
23
18
|
|
24
|
-
|
25
|
-
|
19
|
+
item_index = compute_item_index(index)
|
20
|
+
item_bit_size = compute_item_bit_size(item_index)
|
21
|
+
offset = compute_relative_offset(index, item_bit_size)
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
bit = map_to_bit(value)
|
31
|
-
item_index = compute_item_index(index)
|
32
|
-
item_bit_size = compute_item_bit_size(item_index)
|
33
|
-
offset = compute_relative_offset(index, item_bit_size)
|
34
|
-
|
35
|
-
@internal_array[item_index] =
|
36
|
-
if bit == 1
|
37
|
-
set_bit(@internal_array[item_index], offset)
|
38
|
-
else
|
39
|
-
unset_bit(
|
40
|
-
@internal_array[item_index],
|
41
|
-
offset,
|
42
|
-
item_bit_size
|
43
|
-
)
|
44
|
-
end
|
45
|
-
end
|
23
|
+
get_bit(@internal_array[item_index], offset)
|
24
|
+
end
|
46
25
|
|
47
|
-
|
48
|
-
|
49
|
-
proc ? res.each { |byte| proc.call(byte) } : res.each
|
50
|
-
end
|
26
|
+
def []=(index, value)
|
27
|
+
raise IndexError if index.negative? || index >= @size
|
51
28
|
|
52
|
-
|
53
|
-
|
54
|
-
|
29
|
+
bit = map_to_bit(value)
|
30
|
+
item_index = compute_item_index(index)
|
31
|
+
item_bit_size = compute_item_bit_size(item_index)
|
32
|
+
offset = compute_relative_offset(index, item_bit_size)
|
55
33
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
34
|
+
@internal_array[item_index] =
|
35
|
+
if bit == 1
|
36
|
+
set_bit(@internal_array[item_index], offset)
|
37
|
+
else
|
38
|
+
unset_bit(
|
39
|
+
@internal_array[item_index],
|
40
|
+
offset,
|
41
|
+
item_bit_size
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
61
45
|
|
62
|
-
|
63
|
-
|
46
|
+
def each_byte(&proc)
|
47
|
+
res = decrease_items_size(@internal_array, 8, @bits_per_item)
|
48
|
+
proc ? res.each { |byte| proc.call(byte) } : res.each
|
49
|
+
end
|
64
50
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
else
|
69
|
-
decrease_items_size(@internal_array, value, @bits_per_item)
|
70
|
-
end
|
51
|
+
def to_a
|
52
|
+
@internal_array.clone
|
53
|
+
end
|
71
54
|
|
72
|
-
|
73
|
-
|
55
|
+
def to_s
|
56
|
+
@internal_array.map do |item|
|
57
|
+
format("%0#{@bits_per_item}d", item.to_s(2))
|
58
|
+
end.join(' ')
|
59
|
+
end
|
74
60
|
|
75
|
-
|
61
|
+
def bits_per_item=(value)
|
62
|
+
raise ArgumentError unless [8, 16, 32, 64].include?(value)
|
76
63
|
|
77
|
-
|
78
|
-
if
|
79
|
-
|
64
|
+
@internal_array =
|
65
|
+
if value > @bits_per_item
|
66
|
+
increase_items_size(@internal_array, value, @bits_per_item)
|
80
67
|
else
|
81
|
-
|
68
|
+
decrease_items_size(@internal_array, value, @bits_per_item)
|
82
69
|
end
|
83
|
-
end
|
84
70
|
|
85
|
-
|
86
|
-
|
87
|
-
initial_data.is_a?(Array) ? initial_data.clone : res
|
88
|
-
end
|
71
|
+
@bits_per_item = value
|
72
|
+
end
|
89
73
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
else
|
98
|
-
0
|
99
|
-
end
|
74
|
+
private
|
75
|
+
|
76
|
+
def init_size(initial_data, bits_per_item)
|
77
|
+
if initial_data.is_a?(Array)
|
78
|
+
bits_per_item * initial_data.length
|
79
|
+
else
|
80
|
+
initial_data
|
100
81
|
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def init_internal_array(initial_data, size, bits_per_item)
|
85
|
+
res = [0] * (size / bits_per_item.to_f).ceil
|
86
|
+
initial_data.is_a?(Array) ? initial_data.clone : res
|
87
|
+
end
|
101
88
|
|
102
|
-
|
103
|
-
|
104
|
-
|
89
|
+
def map_to_bit(value)
|
90
|
+
if value
|
91
|
+
if value.is_a?(Integer)
|
92
|
+
value.zero? ? 0 : 1
|
105
93
|
else
|
106
|
-
|
94
|
+
1
|
107
95
|
end
|
96
|
+
else
|
97
|
+
0
|
108
98
|
end
|
99
|
+
end
|
109
100
|
|
110
|
-
|
111
|
-
|
101
|
+
def compute_item_bit_size(index)
|
102
|
+
if index == @internal_array.length - 1
|
103
|
+
size - ((@internal_array.length - 1) * @bits_per_item)
|
104
|
+
else
|
105
|
+
@bits_per_item
|
112
106
|
end
|
107
|
+
end
|
113
108
|
|
114
|
-
|
115
|
-
|
116
|
-
|
109
|
+
def compute_item_index(index)
|
110
|
+
index / @bits_per_item
|
111
|
+
end
|
117
112
|
|
118
|
-
|
119
|
-
|
120
|
-
|
113
|
+
def compute_relative_offset(index, size)
|
114
|
+
size - (index % @bits_per_item) - 1
|
115
|
+
end
|
121
116
|
|
122
|
-
|
123
|
-
|
124
|
-
|
117
|
+
def set_bit(value, offset)
|
118
|
+
value | (2**offset)
|
119
|
+
end
|
125
120
|
|
126
|
-
|
127
|
-
|
128
|
-
|
121
|
+
def unset_bit(value, offset, size)
|
122
|
+
value & (((2**size) - 1) - (2**offset))
|
123
|
+
end
|
129
124
|
|
130
|
-
|
131
|
-
|
132
|
-
|
125
|
+
def get_bit(value, offset)
|
126
|
+
(value >> offset) & 0x1
|
127
|
+
end
|
133
128
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
offset = bpi
|
138
|
-
if processed_bits >= new_size
|
139
|
-
offset = 0
|
140
|
-
acc << 0
|
141
|
-
processed_bits = 0
|
142
|
-
end
|
143
|
-
|
144
|
-
acc[-1] = append_bits(acc[-1], offset, item)
|
145
|
-
processed_bits += bpi
|
146
|
-
end
|
147
|
-
end
|
129
|
+
def append_bits(value, offset, bits)
|
130
|
+
(value << offset) | bits
|
131
|
+
end
|
148
132
|
|
149
|
-
|
150
|
-
|
151
|
-
|
133
|
+
def increase_items_size(array, new_size, bpi)
|
134
|
+
processed_bits = 0
|
135
|
+
array.each_with_object([0]) do |item, acc|
|
136
|
+
offset = bpi
|
137
|
+
if processed_bits >= new_size
|
138
|
+
offset = 0
|
139
|
+
acc << 0
|
140
|
+
processed_bits = 0
|
152
141
|
end
|
142
|
+
|
143
|
+
acc[-1] = append_bits(acc[-1], offset, item)
|
144
|
+
processed_bits += bpi
|
153
145
|
end
|
146
|
+
end
|
154
147
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
148
|
+
def decrease_items_size(array, new_size, bpi)
|
149
|
+
array.each_with_object([]) do |item, acc|
|
150
|
+
acc.concat(explode_item(item, new_size, bpi))
|
151
|
+
end
|
152
|
+
end
|
159
153
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
154
|
+
def explode_item(item, new_size, bpi)
|
155
|
+
res = []
|
156
|
+
offset = bpi
|
157
|
+
mask = (2**new_size) - 1
|
164
158
|
|
165
|
-
|
159
|
+
while offset.positive?
|
160
|
+
offset -= new_size
|
161
|
+
res << ((item >> offset) & mask)
|
166
162
|
end
|
167
163
|
|
168
|
-
|
169
|
-
alias set []=
|
164
|
+
res
|
170
165
|
end
|
166
|
+
|
167
|
+
alias at []
|
168
|
+
alias set []=
|
171
169
|
end
|