]> git.donarmstrong.com Git - biopieces.git/blobdiff - code_ruby/lib/maasha/bitarray.rb
added qual_valid? method to Seq.rb
[biopieces.git] / code_ruby / lib / maasha / bitarray.rb
index 659a9305c8cba7053dc680ddd61ab1e599ed9ff7..81568a08db13c944e70de2c069840ae8a98df072 100644 (file)
@@ -58,16 +58,16 @@ class BitArray
 
   # 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
+    raise BitArrayError, "Position #{pos} must be an integer."                  unless pos.is_a? Fixnum
+    raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size - 1}" unless (0 ... @size ).include? pos
 
     @byte_array[byte_pos(pos)] = @byte_array[byte_pos(pos)] | bit_pos(pos)
   end
 
   # Method to set a bit to 0 at a given position in the bit array.
   def bit_unset(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
+    raise BitArrayError, "Position #{pos} must be an integer."                  unless pos.is_a? Fixnum
+    raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size - 1}" unless (0 ... @size ).include? pos
 
     mask = bit_pos(pos)
     mask = ~mask
@@ -77,8 +77,8 @@ class BitArray
 
   # 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
+    raise BitArrayError, "Position #{pos} must be an integer."                  unless pos.is_a? Fixnum
+    raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size - 1}" unless (0 ... @size ).include? pos
 
     (@byte_array[byte_pos(pos)] & bit_pos(pos)) != 0
   end
@@ -155,43 +155,67 @@ class BitArray
   # Method to set the bits to "on" in an interval in a bit array.
   # Returns the number of bits set.
   def interval_set(start, stop)
-    raise BitArrayError, "interval start < 0 (#{start} < 0)"                       if start < 0
-    raise BitArrayError, "interval stop > bit array size (#{stop} > #{self.size})" if stop  > self.size
-    raise BitArrayError, "interval stop < interval start (#{stop} < #{start})"     if stop  < start
+    raise BitArrayError, "interval start < 0 (#{start} < 0)"                               if start < 0
+    raise BitArrayError, "interval stop > bit array size - 1 (#{stop} > #{self.size - 1})" if stop  > self.size - 1
+    raise BitArrayError, "interval stop < interval start (#{stop} < #{start})"             if stop  < start
 
-    mask = (2 ** BitsInChar) - 1  # 11111111
+    byte_start = start / BitsInChar
+    byte_stop  = stop  / BitsInChar
 
     bits_start = start % BitsInChar
     bits_stop  = stop  % BitsInChar
 
-    mask_start = mask >> bits_start
-    mask_stop  = mask << (BitsInChar - bits_stop)
-
-    self.byte_array[start / BitsInChar] |= mask_start if (stop / BitsInChar) != (start / BitsInChar)
-    self.byte_array[stop /  BitsInChar] |= mask_stop
+    mask = (2 ** BitsInChar) - 1  # 11111111
+    
+    if byte_start == byte_stop
+      self.byte_array[byte_start] |= ((mask >> bits_start) & (mask << (BitsInChar - bits_stop - 1)))
+    else
+      if bits_start != 0
+        self.byte_array[byte_start] |= (mask >> bits_start)
+        byte_start += 1
+      end
 
-    byte_start = (start + BitsInChar - bits_start) / BitsInChar
-    byte_stop  = stop / BitsInChar
+      self.byte_array[byte_stop] |= (mask << (BitsInChar - bits_stop - 1))
 
-    (byte_start ... byte_stop).each do |pos|
-      self.byte_array[pos] |= mask
+      if byte_start != byte_stop
+        self.byte_array[byte_start ... byte_stop] = mask
+      end
     end
 
-    stop - start
+    stop - start + 1
   end
 
   # Method to set the bits to "off" in an interval in a bit array.
   # Returns the number of bits unset.
   def interval_unset(start, stop)
-    raise BitArrayError, "interval start < 0 (#{start} < 0)"                       if start < 0
-    raise BitArrayError, "interval stop > bit array size (#{stop} > #{self.size})" if stop  > self.size
-    raise BitArrayError, "interval stop < interval start (#{stop} < #{start})"     if stop  < start
+    raise BitArrayError, "interval start < 0 (#{start} < 0)"                               if start < 0
+    raise BitArrayError, "interval stop > bit array size - 1 (#{stop} > #{self.size - 1})" if stop  > self.size - 1
+    raise BitArrayError, "interval stop < interval start (#{stop} < #{start})"             if stop  < start
+
+    byte_start = start / BitsInChar
+    byte_stop  = stop  / BitsInChar
+
+    bits_start = start % BitsInChar
+    bits_stop  = stop  % BitsInChar
 
-    (start ... stop).each do |pos|
-      self.bit_unset(pos)
+    mask = (2 ** BitsInChar) - 1  # 11111111
+
+    if byte_start == byte_stop
+      self.byte_array[byte_start] &= ~((mask >> bits_start) & (mask << (BitsInChar - bits_stop - 1)))
+    else
+      if bits_start != 0
+        self.byte_array[byte_start] &= ~(mask >> bits_start)
+        byte_start += 1
+      end
+
+      self.byte_array[byte_stop] &= ~(mask << (BitsInChar - bits_stop - 1))
+
+      if byte_start != byte_stop
+        self.byte_array[byte_start ... byte_stop] = ~mask
+      end
     end
 
-    stop - start
+    stop - start + 1
   end
 
   # Method to locate intervals of bits set to "on" in a bit array.
@@ -199,25 +223,24 @@ class BitArray
   #   BitArray.each_interval { |start, stop| } -> Fixnum
   def each_interval
     intervals = []
-    start     = 0
-    stop      = 0
+    bit_start = 0
+    bit_stop  = 0
 
-    while start < self.size
-      if self.bit_set?(start)
-        stop = start
+    while bit_start < self.size
+      bit_start += 1 while bit_start < self.size and not self.bit_set?(bit_start)
 
-        while stop < self.size and self.bit_set?(stop)
-          stop += 1
-        end
+      if bit_start < self.size
+        bit_stop = bit_start
+        bit_stop  += 1 while bit_stop < self.size and self.bit_set?(bit_stop)
 
         if block_given?
-          yield start, stop
+          yield bit_start, bit_stop - 1
         else
-          intervals << [start, stop]
+          intervals << [bit_start, bit_stop - 1]
         end
-      end
 
-      stop > start ? start = stop : start += 1
+        bit_start = bit_stop + 1
+      end
     end
 
     return intervals unless block_given?