]> git.donarmstrong.com Git - biopieces.git/commitdiff
added bitmap.rb
authormartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Thu, 22 Mar 2012 08:29:21 +0000 (08:29 +0000)
committermartinahansen <martinahansen@74ccb610-7750-0410-82ae-013aeee3265d>
Thu, 22 Mar 2012 08:29:21 +0000 (08:29 +0000)
git-svn-id: http://biopieces.googlecode.com/svn/trunk@1773 74ccb610-7750-0410-82ae-013aeee3265d

code_ruby/lib/maasha/bitmap.rb [new file with mode: 0644]

diff --git a/code_ruby/lib/maasha/bitmap.rb b/code_ruby/lib/maasha/bitmap.rb
new file mode 100644 (file)
index 0000000..d1a1a12
--- /dev/null
@@ -0,0 +1,269 @@
+# Copyright (C) 2012 Martin A. Hansen.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# http://www.gnu.org/copyleft/gpl.html
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+# This software is part of the Biopieces framework (www.biopieces.org).
+
+# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+
+require 'inline'
+
+# Error class for all exceptions to do with Base36.
+class BitMapError < StandardError; end
+
+BitsInChar = 8
+
+class BitMap
+  attr_accessor :byte_array
+
+  def initialize(rows, cols, byte_array = nil)
+    @rows            = rows
+    @cols            = cols
+    @size            = rows * cols
+
+    if byte_array.nil?
+      @byte_array_size = (rows * cols.to_f / BitsInChar).ceil
+      @byte_array      = "\0" * @byte_array_size
+    else
+      @byte_array_size = (rows * cols.to_f / BitsInChar).ceil
+      @byte_array      = byte_array
+    end
+  end
+
+  def slice(rows, cols)
+    rows = rows.first.to_a if rows.first.respond_to? :to_a
+    cols = cols.first.to_a if cols.first.respond_to? :to_a
+
+    new_byte_array_size = (rows.size * cols.size.to_f / BitsInChar).ceil
+    new_byte_array      = "\0" * new_byte_array_size
+
+    slice_c(new_byte_array, rows, cols)
+
+    BitMap.new(rows.size, cols.size, new_byte_array)
+  end
+
+  def flip!
+    @rows, @cols = @cols, @rows
+  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.gsub(/.{#{@cols}}/, "\\0#{$/}")
+  end
+
+  inline do |builder|
+    builder.add_static "rows",            'rb_intern("@rows")',            "ID"
+    builder.add_static "cols",            'rb_intern("@cols")',            "ID"
+    builder.add_static "size",            'rb_intern("@size")',            "ID"
+    builder.add_static "byte_array_size", 'rb_intern("@byte_array_size")', "ID"
+    builder.add_static "byte_array",      'rb_intern("@byte_array")',      "ID"
+
+    builder.prefix %s{
+      unsigned char bit_count[256] = {     
+        0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+      };
+    }
+
+    builder.prefix %{
+      #define COUNT_BITS(c) (bit_count[c])
+    }
+
+    builder.prefix %{
+      #define BYTE_POS(pos) (pos / CHAR_BIT)
+    }
+
+    builder.prefix %{
+      #define BIT_POS(pos) (1 << (CHAR_BIT - 1 - (pos % CHAR_BIT)))
+    }
+
+    builder.c %{
+      void fill_c()
+      {
+        VALUE          _size       = rb_ivar_get(self, byte_array_size);
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        int            size        = NUM2INT(_size);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+        int            i           = 0;
+      
+        for (i = 0; i < size; i++) byte_array[i] = ~0;
+      }
+    }
+
+    builder.c %{
+      void empty_c()
+      {
+        VALUE          _size       = rb_ivar_get(self, byte_array_size);
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        int            size        = NUM2INT(_size);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+        int            i           = 0;
+      
+        for (i = 0; i < size; i++) byte_array[i] = 0;
+      }
+    }
+
+    builder.c %{
+      void bit_set_c(int row, int col)
+      {
+        VALUE          _rows       = rb_ivar_get(self, rows);
+        VALUE          _cols       = rb_ivar_get(self, cols);
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        int            rows        = NUM2INT(_rows);
+        int            cols        = NUM2INT(_cols);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+        int            pos         = 0;
+
+        if (row >= rows)
+          rb_raise(rb_eval_string("BitMapError"), "row out of range: %d >= %d\\n", row, rows);
+
+        if (col >= cols)
+          rb_raise(rb_eval_string("BitMapError"), "col out of range: %d >= %d\\n", col, cols);
+
+        pos = row * cols + col;
+
+        byte_array[BYTE_POS(pos)] |= BIT_POS(pos);
+      }
+    }
+
+    builder.c %{
+      VALUE bit_test_c(int pos)
+      {
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+
+        return ((byte_array[BYTE_POS(pos)] & BIT_POS(pos)) != 0);
+      }
+    }
+
+    builder.c %{
+      void slice_c(char* new_array, VALUE _new_rows, VALUE _new_cols)
+      {
+        VALUE          _old_array  = rb_ivar_get(self, byte_array);
+        VALUE          _old_rows   = rb_ivar_get(self, rows);
+        VALUE          _old_cols   = rb_ivar_get(self, cols);
+        unsigned char* old_array   = StringValuePtr(_old_array);
+        int            old_rows    = NUM2INT(_old_rows);
+        int            old_cols    = NUM2INT(_old_cols);
+
+        VALUE          *rows_array = RARRAY_PTR(_new_rows);
+        VALUE          *cols_array = RARRAY_PTR(_new_cols);
+        int            row_count   = (int) RARRAY_LEN(_new_rows);
+        int            col_count   = (int) RARRAY_LEN(_new_cols);
+        int            r           = 0;
+        int            c           = 0;
+        int            old_pos     = 0;
+        int            new_pos     = 0;
+
+        for (r = 0; r < row_count; r++)
+        {
+          for (c = 0; c < col_count; c++)
+          {
+            old_pos = NUM2INT(rows_array[r]) * old_cols + NUM2INT(cols_array[c]);
+            new_pos = r * col_count + c;
+
+            new_array[BYTE_POS(new_pos)] |= BIT_POS(new_pos) & (old_array[BYTE_POS(old_pos)] & BIT_POS(old_pos));
+          }
+        }
+      }
+    }
+
+    builder.c %{
+      VALUE sum_c()
+      {
+        VALUE          _size       = rb_ivar_get(self, byte_array_size);
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        int            size        = NUM2INT(_size);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+        int            i           = 0;
+        int            sum         = 0;
+      
+        for (i = 0; i < size; i++)
+          sum += COUNT_BITS(byte_array[i]);
+
+        return INT2NUM(sum);
+      }
+    }
+
+    builder.c %{
+      VALUE sum_rows_c()
+      {
+        VALUE          _rows       = rb_ivar_get(self, rows);
+        VALUE          _cols       = rb_ivar_get(self, cols);
+        VALUE          _byte_array = rb_ivar_get(self, byte_array);
+        int            rows        = NUM2INT(_rows);
+        int            cols        = NUM2INT(_cols);
+        unsigned char* byte_array  = StringValuePtr(_byte_array);
+        int            row         = 0;
+        int            col         = 0;
+        int            sums[rows];
+        VALUE          rb_sums     = rb_ary_new();
+
+        int pos = 0;
+
+        for (row = 0; row < rows; row++) sums[row] = 0;
+
+        for (row = 0; row < rows; row++)
+        {
+          for (col = 0; col < cols; col++)
+          {
+            pos = row * cols + col;
+            sums[row] += ((byte_array[BYTE_POS(pos)] & BIT_POS(pos)) != 0);
+          }
+        }
+
+        for (row = 0; row < rows; row++) rb_ary_push(rb_sums, INT2FIX(sums[row]));
+      
+        return rb_sums;
+      }
+    }
+  end
+
+  alias :sum :sum_c
+  alias :sum_rows :sum_rows_c
+  alias :bit_set :bit_set_c
+  alias :bit_set? :bit_test_c
+  alias :fill! :fill_c
+  alias :empty! :empty_c
+  alias :zero! :empty_c
+end