Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #1 from mceachen/master

TLC
  • Loading branch information...
commit 467499032c4b852d410262f73681db56d4f1728b 2 parents 9fe36be + 265f33b
@peterc authored
View
2  Gemfile
@@ -1,4 +1,2 @@
source "http://rubygems.org"
-
-# Specify your gem's dependencies in bitarray.gemspec
gemspec
View
20 Gemfile.lock
@@ -0,0 +1,20 @@
+PATH
+ remote: .
+ specs:
+ bitarray (0.0.5)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ rake (0.9.2.2)
+ test-unit (2.4.5)
+ yard (0.7.4)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ bitarray!
+ rake
+ test-unit
+ yard
View
45 README.md
@@ -2,32 +2,57 @@
Basic, pure Ruby bit field. Pretty fast (for what it is) and memory efficient. Works well for Bloom filters (the reason I wrote it).
-Written in 2007 and not updated since then, just bringing it on to GitHub by user request. It used to be called Bitfield and was hosted at http://snippets.dzone.com/posts/show/4234 .. I will review the code and bring the docs up to date in due course.
+Written in 2007 and not updated since then, just bringing it on to GitHub by user request. It used to be called BitField and was hosted at http://snippets.dzone.com/posts/show/4234 .. I will review the code and bring the docs up to date in due course.
## Installation
- gem install bitarray
+```ruby
+gem install bitarray
+```
## Examples
To use:
- require 'bitarray'
+```ruby
+require 'bitarray'
+```
-Create a bit field 1000 bits wide:
+Create a bit array 1000 bits wide:
- ba = BitArray.new(1000)
+```ruby
+ba = BitArray.new(1000)
+```
Setting and reading bits:
- ba[100] = 1
- ba[100] .. => 1
- ba[100] = 0
+```ruby
+ba[100] = 1
+ba[100]
+#=> 1
+
+ba[100] = 0
+ba[100]
+#=> 0
+```
More:
- ba.to_s = "10101000101010101" (example)
- ba.total_set .. => 10 (example - 10 bits are set to "1")
+```ruby
+ba = BitArray.new(20)
+[1,3,5,9,11,13,15].each { |i| ba[i] = 1 }
+ba.to_s
+#=> "01010100010101010000"
+ba.total_set
+#=> 7
+```
+
+## History
+- v5 (added support for flags being on by default, instead of off)
+- v4 (fixed bug where setting 0 bits to 0 caused a set to 1)
+- v3 (supports dynamic bitwidths for array elements.. now doing 32 bit widths default)
+- v2 (now uses 1 << y, rather than 2 ** y .. it's 21.8 times faster!)
+- v1 (first release)
## License
View
8 bitarray.gemspec
@@ -1,9 +1,11 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
+require 'bitarray'
+
Gem::Specification.new do |s|
s.name = "bitarray"
- s.version = "0.0.1"
+ s.version = BitArray::VERSION
s.authors = ["Peter Cooper"]
s.email = ["git@peterc.org"]
s.homepage = "https://github.com/peterc/bitarray"
@@ -16,4 +18,8 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
+
+ s.add_development_dependency "rake"
+ s.add_development_dependency "yard"
+ s.add_development_dependency "test-unit"
end
View
19 lib/bitarray.rb
@@ -1,14 +1,15 @@
class BitArray
attr_reader :size
include Enumerable
-
+ VERSION = "0.0.5"
ELEMENT_WIDTH = 32
-
- def initialize(size)
+
+ def initialize(size, default_value = 0)
@size = size
@field = Array.new(((size - 1) / ELEMENT_WIDTH) + 1, 0)
+ @field.map!{|i| ~i} if (default_value == 1)
end
-
+
# Set a bit (1/0)
def []=(position, value)
if value == 1
@@ -17,22 +18,22 @@ def []=(position, value)
@field[position / ELEMENT_WIDTH] ^= 1 << (position % ELEMENT_WIDTH)
end
end
-
+
# Read a bit (1/0)
def [](position)
@field[position / ELEMENT_WIDTH] & 1 << (position % ELEMENT_WIDTH) > 0 ? 1 : 0
end
-
+
# Iterate over each bit
def each(&block)
@size.times { |position| yield self[position] }
end
-
+
# Returns the field as a string like "0101010100111100," etc.
def to_s
- inject("") { |a, b| a + b.to_s }
+ @field.collect{|ea| ("%032b" % ea).reverse}.join[0..@size-1]
end
-
+
# Returns the total number of bits that are set
# (The technique used here is about 6 times faster than using each or inject direct on the bitfield)
def total_set
View
75 test/test_bitarray.rb
@@ -2,61 +2,78 @@
require "bitarray"
class TestBitArray < Test::Unit::TestCase
+
def setup
- @public_bf = BitArray.new(1000)
+ @public_ba = BitArray.new(1000)
end
-
+
def test_basic
assert_equal 0, BitArray.new(100)[0]
assert_equal 0, BitArray.new(100)[1]
end
-
+
def test_setting_and_unsetting
- @public_bf[100] = 1
- assert_equal 1, @public_bf[100]
- @public_bf[100] = 0
- assert_equal 0, @public_bf[100]
+ @public_ba[100] = 1
+ assert_equal 1, @public_ba[100]
+ @public_ba[100] = 0
+ assert_equal 0, @public_ba[100]
end
def test_random_setting_and_unsetting
100.times do
index = rand(1000)
- @public_bf[index] = 1
- assert_equal 1, @public_bf[index]
- @public_bf[index] = 0
- assert_equal 0, @public_bf[index]
+ @public_ba[index] = 1
+ assert_equal 1, @public_ba[index]
+ @public_ba[index] = 0
+ assert_equal 0, @public_ba[index]
end
end
-
+
+ def test_random_side_effects
+ ba2 = BitArray.new(@public_ba.size, 1)
+
+ on = (@public_ba.size / 2).times.collect do
+ index = rand(@public_ba.size)
+ @public_ba[index] = 1
+ ba2[index] = 0
+ index
+ end
+ assert_equal(@public_ba.to_s, @public_ba.to_s_fast)
+
+ @public_ba.size.times do |i|
+ assert_equal(@public_ba[i], on.include?(i) ? 1 : 0)
+ assert_equal(ba2[i], on.include?(i) ? 0 : 1)
+ end
+ end
+
def test_multiple_setting
1.upto(999) do |pos|
- 2.times { @public_bf[pos] = 1 }
- assert_equal 1, @public_bf[pos]
+ 2.times { @public_ba[pos] = 1 }
+ assert_equal 1, @public_ba[pos]
end
end
def test_multiple_unsetting
1.upto(999) do |pos|
- 2.times { @public_bf[pos] = 0 }
- assert_equal 0, @public_bf[pos]
+ 2.times { @public_ba[pos] = 0 }
+ assert_equal 0, @public_ba[pos]
end
end
-
+
def test_size
- assert_equal 1000, @public_bf.size
+ assert_equal 1000, @public_ba.size
end
-
+
def test_to_s
- bf = BitArray.new(10)
- bf[1] = 1
- bf[5] = 1
- assert_equal "0100010000", bf.to_s
+ ba = BitArray.new(35)
+ [1, 5, 6, 7, 10, 16, 33].each{|i|ba[i] = 1}
+ assert_equal "01000111001000001000000000000000010", ba.to_s
end
-
+
def test_total_set
- bf = BitArray.new(10)
- bf[1] = 1
- bf[5] = 1
- assert_equal 2, bf.total_set
+ ba = BitArray.new(10)
+ ba[1] = 1
+ ba[5] = 1
+ assert_equal 2, ba.total_set
end
-end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.