]> git.donarmstrong.com Git - biopieces.git/commitdiff
added bitarray ruby code
authormartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Fri, 14 Jan 2011 16:26:18 +0000 (16:26 +0000)
committermartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Fri, 14 Jan 2011 16:26:18 +0000 (16:26 +0000)
git-svn-id: http://biopieces.googlecode.com/svn/trunk@1202 74ccb610-7750-0410-82ae-013aeee3265d

code_ruby/Maasha/lib/bitarray.rb [new file with mode: 0644]
code_ruby/Maasha/test/test_bitarray.rb [new file with mode: 0755]

diff --git a/code_ruby/Maasha/lib/bitarray.rb b/code_ruby/Maasha/lib/bitarray.rb
new file mode 100644 (file)
index 0000000..5533c52
--- /dev/null
@@ -0,0 +1,158 @@
+BitsInChar = 8
+
+# Error class for all exceptions to do with BitArray.
+class BitArrayError < StandardError; end
+
+# Class containing methods for creating and manipulating a bit array.
+class BitArray
+  attr_reader :size, :byte_array
+
+  # Method to initialize a new bit array of a given size.
+  def initialize(size)
+    @size        = size
+    @byte_array  = init_byte_array
+    @count_table = init_count_table
+  end
+
+  # Method to set a bit to 1 at a given position in the bit array.
+  def bit_set(pos)
+    raise BitArrayError, "Position #{pos} must be an integer."              unless pos.is_a? Fixnum
+    raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size}" unless (0 ... @size ).include? pos
+
+    @byte_array[byte_pos(pos)] = (@byte_array[byte_pos(pos)].ord | bit_pos(pos)).chr
+  end
+
+  # Method to check if a bit at a given position in the bit array is set.
+  def bit_set?(pos)
+    raise BitArrayError, "Position #{pos} must be an integer."              unless pos.is_a? Fixnum
+    raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size}" unless (0 ... @size ).include? pos
+
+    (@byte_array[byte_pos(pos)].ord & bit_pos(pos)) != 0
+  end
+
+  # Method that returns the number of bits set "on" in a bit array.
+  def bits_on1
+    bits_on = 0
+
+    (0 ... @size).each do |pos|
+      bits_on += 1 if bit_set?(pos)
+    end
+
+    bits_on
+  end
+
+  # Method that returns the number of bits set "on" in a bit array.
+  def bits_on 
+    bits_on = 0
+
+    (0 ... self.byte_array.size).each do |byte|
+      bits_on += @count_table[byte]
+    end
+
+    bits_on
+  end
+
+  # Method that returns the number of bits set "off" in a bit array.
+  def bits_off
+    @size - bits_on
+  end
+
+  # Method to run bitwise AND (&) on two bit arrays and return the
+  # result in a new bit array. Bits are copied if they exists in BOTH operands.
+  # 00111100 & 00001101 = 00001100
+  def &(ba)
+    raise BitArrayError, "uneven size of bit arrays: #{self.size} vs #{ba.size}" if self.size != ba.size
+
+    result = BitArray.new(ba.size)
+
+    (0 ... ba.byte_array.size).each do |byte|
+      result.byte_array[byte] = (self.byte_array[byte].ord & ba.byte_array[byte].ord).chr
+    end
+
+    result
+  end
+
+  # Method to run bitwise OR (|) on two bit arrays and return the
+  # result in a new bit array. Bits are copied if they exists in EITHER operands.
+  # 00111100 | 00001101 = 00111101
+  def |(ba)
+    raise BitArrayError, "uneven size of bit arrays: #{self.size} vs #{ba.size}" if self.size != ba.size
+
+    result = BitArray.new(ba.size)
+
+    (0 ... ba.byte_array.size).each do |byte|
+      result.byte_array[byte] = (self.byte_array[byte].ord | ba.byte_array[byte].ord).chr
+    end
+
+    result
+  end
+
+  # Method to run bitwise XOR (^) on two bit arrays and return the
+  # result in a new bit array. Bits are copied if they exists in ONE BUT NOT BOTH operands.
+  # 00111100 ^ 00001101 = 00110001
+  def ^(ba)
+    raise BitArrayError, "uneven size of bit arrays: #{self.size} vs #{ba.size}" if self.size != ba.size
+
+    result = BitArray.new(ba.size)
+
+    (0 ... ba.byte_array.size).each do |byte|
+      result.byte_array[byte] = (self.byte_array[byte].ord ^ ba.byte_array[byte].ord).chr
+    end
+
+    result
+  end
+
+  # Method to convert a bit array to a string.
+  def to_s
+    string = ""
+
+    (0 ... @size).each do |pos|
+      if self.bit_set? pos 
+        string << "1"
+      else
+        string << "0"
+      end
+    end
+
+    string
+  end
+
+  private
+
+  # Method to initialize the byte array (string) that constitutes the bit array.
+  def init_byte_array
+    raise BitArrayError, "Size must be an integer, not #{@size}" unless @size.is_a? Fixnum
+    raise BitArrayError, "Size must be positive, not #{@size}"   unless @size > 0
+
+    byte_array = ""
+    byte_array << 0.chr * (((@size - 1) / BitsInChar) + 1)
+
+    byte_array
+  end
+
+  # Method that creates a table with number of bits set.
+  def init_count_table
+    count_table = []
+
+    bits = 0
+
+    (0 ... BitsInChar).each do |i|
+      (0 ... BitsInChar).each do |c|
+        bits += 1
+      end
+    end
+
+    puts bits
+  end
+
+  # Method that returns the byte position in the byte array for a given bit position.
+  def byte_pos(pos)
+    pos / BitsInChar
+  end
+
+  # Method that returns the bit position in a byte.
+  def bit_pos(pos)
+    1 << (BitsInChar - 1 - (pos % BitsInChar))
+  end
+end
+
diff --git a/code_ruby/Maasha/test/test_bitarray.rb b/code_ruby/Maasha/test/test_bitarray.rb
new file mode 100755 (executable)
index 0000000..c077932
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/env ruby
+
+require 'bitarray'
+require 'test/unit'
+require 'pp'
+
+class TestBitArray < Test::Unit::TestCase 
+  def setup
+    @ba = BitArray.new(10)
+  end
+
+  def test_BitArray_initialize_raises_on_bad_sizes
+    [ -1, 0, 1.1, "a" ].each do |size|
+      assert_raise(BitArrayError) { BitArray.new(size) }
+    end
+  end
+
+  def test_BitArray_initialize_dont_raise_on_ok_sizes
+    [ 1, 10, 1000 ].each do |size|
+      assert_nothing_raised { BitArray.new(size) }
+    end
+  end
+
+  def test_BitArray_size_returns_correctly
+    assert_equal(10, @ba.size)
+  end
+
+  def test_BitArray_to_s_returns_correctly
+    assert_equal("0000000000", @ba.to_s)
+  end
+
+  def test_BitArray_bit_set_with_bad_pos_raises
+    [-1, 10, 1.1].each do |pos|
+      assert_raise(BitArrayError) { @ba.bit_set(pos) }
+    end
+  end
+
+  def test_BitArray_bit_set
+    str = "0000000000"
+
+    (0.upto 9).each do |pos|
+      @ba.bit_set(pos)
+      str[pos] = "1"
+      assert_equal(str, @ba.to_s)
+    end
+  end
+
+  def test_BitArray_bit_set_questionmark_with_bad_pos_raises
+    [-1, 10, 1.1].each do |pos|
+      assert_raise(BitArrayError) { @ba.bit_set?(pos) }
+    end
+  end
+
+  def test_BitArray_bit_set_questionmark
+    (0.upto 9).each do |pos|
+      @ba.bit_set(pos)
+      assert_equal(true, @ba.bit_set?(pos))
+    end
+  end
+
+  def test_BitArray_bits_on_returns_correctly
+    @ba.bit_set(4)
+    assert_equal(1, @ba.bits_on)
+  end
+
+  def test_BitArray_bits_off_returns_correctly
+    @ba.bit_set(4)
+    assert_equal(9, @ba.bits_off)
+  end
+
+  def test_BitArray_and_with_uneven_sizes_raises
+    ba = BitArray.new(11)
+    assert_raise(BitArrayError) { @ba & ba }
+  end
+
+  def test_BitArray_AND_returns_correctly
+    ba = BitArray.new(10)
+    @ba.bit_set(4)
+    @ba.bit_set(5)
+    ba.bit_set(5)
+    ba.bit_set(6)
+    assert_equal( "0000010000", (@ba & ba).to_s)
+  end
+
+  def test_BitArray_AND_EQUAL_returns_correctly
+    ba = BitArray.new(10)
+    @ba.bit_set(4)
+    @ba.bit_set(5)
+    ba.bit_set(5)
+    ba.bit_set(6)
+    @ba &= ba
+    assert_equal( "0000010000", @ba.to_s)
+  end
+
+  def test_BitArray_OR_returns_correctly
+    ba = BitArray.new(10)
+    @ba.bit_set(4)
+    @ba.bit_set(5)
+    ba.bit_set(5)
+    ba.bit_set(6)
+    assert_equal( "0000111000", (@ba | ba).to_s)
+  end
+
+  def test_BitArray_XOR_returns_correctly
+    ba = BitArray.new(10)
+    @ba.bit_set(4)
+    @ba.bit_set(5)
+    ba.bit_set(5)
+    ba.bit_set(6)
+    assert_equal( "0000101000", (@ba ^ ba).to_s)
+  end
+end
+
+
+__END__
+