bitarray 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +1 -3
- data/README.md +55 -13
- data/Rakefile +2 -2
- data/bitarray.gemspec +8 -5
- data/lib/bitarray-array.rb +43 -0
- data/lib/bitarray.rb +18 -17
- data/memory-test.rb +13 -0
- data/test/test_bitarray.rb +32 -32
- metadata +43 -15
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c79a60a3580af853940651ca520abd24f359fc97
|
4
|
+
data.tar.gz: 96cb2ffe5551ac793e33f3eb06563aadcc6cfd1d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bcd93a192a22cf477b45cd582028a3cd60c090dd9cdfbfd5b507a86f4c996a1dede387926d34f0495441cb90b0d899c96d5bb9a34dc8b16b5e933794f0e89bf1
|
7
|
+
data.tar.gz: cb2b120ce2abe9242bfc07ac9f1dff0bff7aab271daabaaafca53f39a06be8ce690946575bc6c423e8258fbf99c284ab783301327c0495bb37477798a0def376
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,23 +1,65 @@
|
|
1
|
-
# BitArray: A simple bit
|
1
|
+
# BitArray: A simple bit-array/bitfield library in pure Ruby
|
2
2
|
|
3
|
-
Basic, pure Ruby bit field.
|
3
|
+
Basic, pure Ruby bit field. Works well for Bloom filters (the use case for which I originally wrote it).
|
4
4
|
|
5
|
-
|
5
|
+
Originally written in 2007 and left without significant update until 2017, it has now been updated to work within a typical, modern Ruby environment while maintaining the same API.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem install bitarray
|
11
|
+
```
|
6
12
|
|
7
13
|
## Examples
|
8
14
|
|
9
|
-
|
10
|
-
|
15
|
+
To use:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
require 'bitarray'
|
19
|
+
```
|
20
|
+
|
21
|
+
Create a bit array 1000 bits wide:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
ba = BitArray.new(1000)
|
25
|
+
```
|
26
|
+
|
27
|
+
Setting and reading bits:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
ba[100] = 1
|
31
|
+
ba[100]
|
32
|
+
#=> 1
|
33
|
+
|
34
|
+
ba[100] = 0
|
35
|
+
ba[100]
|
36
|
+
#=> 0
|
37
|
+
```
|
38
|
+
|
39
|
+
More:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
ba = BitArray.new(20)
|
43
|
+
[1,3,5,9,11,13,15].each { |i| ba[i] = 1 }
|
44
|
+
ba.to_s
|
45
|
+
#=> "01010100010101010000"
|
46
|
+
ba.total_set
|
47
|
+
#=> 7
|
48
|
+
```
|
49
|
+
|
50
|
+
## History
|
51
|
+
- 1.0 in 2017 (updated for modern Ruby, more efficient storage, and 10th birthday)
|
52
|
+
- 0.0.1 in 2012 (original v5 released on GitHub)
|
53
|
+
- v5 (added support for flags being on by default, instead of off)
|
54
|
+
- v4 (fixed bug where setting 0 bits to 0 caused a set to 1)
|
55
|
+
- v3 (supports dynamic bitwidths for array elements.. now doing 32 bit widths default)
|
56
|
+
- v2 (now uses 1 << y, rather than 2 ** y .. it's 21.8 times faster!)
|
57
|
+
- v1 (first release)
|
11
58
|
|
12
|
-
|
13
|
-
bf[100] = 1
|
14
|
-
bf[100] .. => 1
|
15
|
-
bf[100] = 0
|
59
|
+
## Thanks
|
16
60
|
|
17
|
-
|
18
|
-
bf.to_s = "10101000101010101" (example)
|
19
|
-
bf.total_set .. => 10 (example - 10 bits are set to "1")
|
61
|
+
Thanks to Michael Slade for encouraging me to update this library on its 10th birthday and for suggesting finally using String's getbyte and setbyte methods now that we're all on 1.9+ compatible implementations.
|
20
62
|
|
21
63
|
## License
|
22
64
|
|
23
|
-
MIT licensed. Copyright 2007-
|
65
|
+
MIT licensed. Copyright 2007-2017 Peter Cooper.
|
data/Rakefile
CHANGED
data/bitarray.gemspec
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
$:.push File.expand_path("../lib", __FILE__)
|
3
3
|
|
4
|
+
require 'bitarray'
|
5
|
+
|
4
6
|
Gem::Specification.new do |s|
|
5
7
|
s.name = "bitarray"
|
6
|
-
s.version =
|
8
|
+
s.version = BitArray::VERSION
|
7
9
|
s.authors = ["Peter Cooper"]
|
8
10
|
s.email = ["git@peterc.org"]
|
9
11
|
s.homepage = "https://github.com/peterc/bitarray"
|
10
|
-
s.summary = %q{A simple, pure Ruby bit
|
11
|
-
s.description = %q{A simple, pure Ruby bit
|
12
|
-
|
13
|
-
s.rubyforge_project = "bitarray"
|
12
|
+
s.summary = %q{A simple, pure Ruby bit-array / bitfield implementation.}
|
13
|
+
s.description = %q{A simple, pure Ruby bit-array / bitfield implementation.}
|
14
14
|
|
15
15
|
s.files = `git ls-files`.split("\n")
|
16
16
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency "rake"
|
21
|
+
s.add_development_dependency "minitest"
|
19
22
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class BitArray
|
2
|
+
attr_reader :size
|
3
|
+
attr_reader :field
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
VERSION = "1.0.0"
|
7
|
+
ELEMENT_WIDTH = 32
|
8
|
+
|
9
|
+
def initialize(size, field = nil)
|
10
|
+
@size = size
|
11
|
+
@field = field || Array.new(((size - 1) / ELEMENT_WIDTH) + 1, 0)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Set a bit (1/0)
|
15
|
+
def []=(position, value)
|
16
|
+
if value == 1
|
17
|
+
@field[position / ELEMENT_WIDTH] |= 1 << (position % ELEMENT_WIDTH)
|
18
|
+
elsif (@field[position / ELEMENT_WIDTH]) & (1 << (position % ELEMENT_WIDTH)) != 0
|
19
|
+
@field[position / ELEMENT_WIDTH] ^= 1 << (position % ELEMENT_WIDTH)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Read a bit (1/0)
|
24
|
+
def [](position)
|
25
|
+
@field[position / ELEMENT_WIDTH] & 1 << (position % ELEMENT_WIDTH) > 0 ? 1 : 0
|
26
|
+
end
|
27
|
+
|
28
|
+
# Iterate over each bit
|
29
|
+
def each(&block)
|
30
|
+
@size.times { |position| yield self[position] }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the field as a string like "0101010100111100," etc.
|
34
|
+
def to_s
|
35
|
+
@field.collect{|ea| ("%0#{ELEMENT_WIDTH}b" % ea).reverse}.join[0..@size-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the total number of bits that are set
|
39
|
+
# (The technique used here is about 6 times faster than using each or inject direct on the bitfield)
|
40
|
+
def total_set
|
41
|
+
@field.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
|
42
|
+
end
|
43
|
+
end
|
data/lib/bitarray.rb
CHANGED
@@ -1,41 +1,42 @@
|
|
1
1
|
class BitArray
|
2
2
|
attr_reader :size
|
3
|
+
attr_reader :field
|
3
4
|
include Enumerable
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(size)
|
5
|
+
|
6
|
+
VERSION = "1.0.0"
|
7
|
+
|
8
|
+
def initialize(size, field = nil)
|
8
9
|
@size = size
|
9
|
-
@field =
|
10
|
+
@field = "\0" * (size / 8 + 1)
|
10
11
|
end
|
11
|
-
|
12
|
+
|
12
13
|
# Set a bit (1/0)
|
13
14
|
def []=(position, value)
|
14
15
|
if value == 1
|
15
|
-
@field
|
16
|
-
|
17
|
-
@field
|
16
|
+
@field.setbyte(position >> 3, @field.getbyte(position >> 3) | (1 << (position % 8)))
|
17
|
+
else
|
18
|
+
@field.setbyte(position >> 3, @field.getbyte(position >> 3) ^ (1 << (position % 8)))
|
18
19
|
end
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
# Read a bit (1/0)
|
22
23
|
def [](position)
|
23
|
-
@field
|
24
|
+
(@field.getbyte(position >> 3) & (1 << (position % 8))) > 0 ? 1 : 0
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
# Iterate over each bit
|
27
28
|
def each(&block)
|
28
29
|
@size.times { |position| yield self[position] }
|
29
30
|
end
|
30
|
-
|
31
|
+
|
31
32
|
# Returns the field as a string like "0101010100111100," etc.
|
32
33
|
def to_s
|
33
|
-
|
34
|
+
@field.bytes.collect{|ea| ("%08b" % ea).reverse}.join[0, @size]
|
34
35
|
end
|
35
|
-
|
36
|
+
|
36
37
|
# Returns the total number of bits that are set
|
37
38
|
# (The technique used here is about 6 times faster than using each or inject direct on the bitfield)
|
38
39
|
def total_set
|
39
|
-
@field.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
|
40
|
+
@field.bytes.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
|
40
41
|
end
|
41
|
-
end
|
42
|
+
end
|
data/memory-test.rb
ADDED
data/test/test_bitarray.rb
CHANGED
@@ -1,62 +1,62 @@
|
|
1
|
-
require "
|
1
|
+
require "minitest/autorun"
|
2
2
|
require "bitarray"
|
3
3
|
|
4
|
-
class TestBitArray < Test
|
4
|
+
class TestBitArray < Minitest::Test
|
5
5
|
def setup
|
6
|
-
@
|
6
|
+
@public_ba = BitArray.new(1000)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def test_basic
|
10
10
|
assert_equal 0, BitArray.new(100)[0]
|
11
|
-
assert_equal 0, BitArray.new(100)[
|
11
|
+
assert_equal 0, BitArray.new(100)[99]
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def test_setting_and_unsetting
|
15
|
-
@
|
16
|
-
assert_equal 1, @
|
17
|
-
@
|
18
|
-
assert_equal 0, @
|
15
|
+
@public_ba[100] = 1
|
16
|
+
assert_equal 1, @public_ba[100]
|
17
|
+
@public_ba[100] = 0
|
18
|
+
assert_equal 0, @public_ba[100]
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_random_setting_and_unsetting
|
22
22
|
100.times do
|
23
23
|
index = rand(1000)
|
24
|
-
@
|
25
|
-
assert_equal 1, @
|
26
|
-
@
|
27
|
-
assert_equal 0, @
|
24
|
+
@public_ba[index] = 1
|
25
|
+
assert_equal 1, @public_ba[index]
|
26
|
+
@public_ba[index] = 0
|
27
|
+
assert_equal 0, @public_ba[index]
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def test_multiple_setting
|
32
32
|
1.upto(999) do |pos|
|
33
|
-
2.times { @
|
34
|
-
assert_equal 1, @
|
33
|
+
2.times { @public_ba[pos] = 1 }
|
34
|
+
assert_equal 1, @public_ba[pos]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_multiple_unsetting
|
39
39
|
1.upto(999) do |pos|
|
40
|
-
2.times { @
|
41
|
-
assert_equal 0, @
|
40
|
+
2.times { @public_ba[pos] = 0 }
|
41
|
+
assert_equal 0, @public_ba[pos]
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
def test_size
|
46
|
-
assert_equal 1000, @
|
46
|
+
assert_equal 1000, @public_ba.size
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
def test_to_s
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
assert_equal "0100010000", bf.to_s
|
50
|
+
ba = BitArray.new(35)
|
51
|
+
[1, 5, 6, 7, 10, 16, 33].each{|i|ba[i] = 1}
|
52
|
+
assert_equal "01000111001000001000000000000000010", ba.to_s
|
54
53
|
end
|
55
|
-
|
54
|
+
|
56
55
|
def test_total_set
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
ba = BitArray.new(10)
|
57
|
+
ba[1] = 1
|
58
|
+
ba[5] = 1
|
59
|
+
ba[9] = 1
|
60
|
+
assert_equal 3, ba.total_set
|
61
61
|
end
|
62
|
-
end
|
62
|
+
end
|
metadata
CHANGED
@@ -1,54 +1,82 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitarray
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Peter Cooper
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
11
|
+
date: 2017-01-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: A simple, pure Ruby bit-array / bitfield implementation.
|
15
42
|
email:
|
16
43
|
- git@peterc.org
|
17
44
|
executables: []
|
18
45
|
extensions: []
|
19
46
|
extra_rdoc_files: []
|
20
47
|
files:
|
21
|
-
- .gitignore
|
48
|
+
- ".gitignore"
|
22
49
|
- Gemfile
|
50
|
+
- Gemfile.lock
|
23
51
|
- README.md
|
24
52
|
- Rakefile
|
25
53
|
- bitarray.gemspec
|
54
|
+
- lib/bitarray-array.rb
|
26
55
|
- lib/bitarray.rb
|
56
|
+
- memory-test.rb
|
27
57
|
- test/test_bitarray.rb
|
28
58
|
homepage: https://github.com/peterc/bitarray
|
29
59
|
licenses: []
|
60
|
+
metadata: {}
|
30
61
|
post_install_message:
|
31
62
|
rdoc_options: []
|
32
63
|
require_paths:
|
33
64
|
- lib
|
34
65
|
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
66
|
requirements:
|
37
|
-
- -
|
67
|
+
- - ">="
|
38
68
|
- !ruby/object:Gem::Version
|
39
69
|
version: '0'
|
40
70
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
71
|
requirements:
|
43
|
-
- -
|
72
|
+
- - ">="
|
44
73
|
- !ruby/object:Gem::Version
|
45
74
|
version: '0'
|
46
75
|
requirements: []
|
47
|
-
rubyforge_project:
|
48
|
-
rubygems_version:
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.6.8
|
49
78
|
signing_key:
|
50
|
-
specification_version:
|
51
|
-
summary: A simple, pure Ruby bit
|
79
|
+
specification_version: 4
|
80
|
+
summary: A simple, pure Ruby bit-array / bitfield implementation.
|
52
81
|
test_files:
|
53
82
|
- test/test_bitarray.rb
|
54
|
-
has_rdoc:
|