X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=code_ruby%2Flib%2Fmaasha%2Fbitarray.rb;h=81568a08db13c944e70de2c069840ae8a98df072;hb=123dbbd20d587b61d0589aa17031ff1796998313;hp=1b2bc9ea212268c5650f44c63c58f2a6d6ceaf99;hpb=990d0af5b6ffd27c9cb81dc7811dfbf077bebb26;p=biopieces.git diff --git a/code_ruby/lib/maasha/bitarray.rb b/code_ruby/lib/maasha/bitarray.rb index 1b2bc9e..81568a0 100644 --- a/code_ruby/lib/maasha/bitarray.rb +++ b/code_ruby/lib/maasha/bitarray.rb @@ -23,6 +23,7 @@ # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< require 'narray' +require 'pp' BitsInChar = 8 @@ -57,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 @@ -76,21 +77,17 @@ 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 # Method that returns the number of bits set "on" in a bit array. - def bits_on - bits_on = 0 - - self.byte_array.each do |byte| - bits_on += @count_array[byte] - end - - bits_on + def bits_on + index = NArray.sint(*self.byte_array.shape) + index[] = self.byte_array + NArray.to_na(@count_array)[index].sum end # Method that returns the number of bits set "off" in a bit array. @@ -158,29 +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 + + byte_start = start / BitsInChar + byte_stop = stop / BitsInChar + + bits_start = start % BitsInChar + bits_stop = stop % BitsInChar + + 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 - (start ... stop).each do |pos| - self.bit_set(pos) + 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 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. @@ -188,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?