# 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
- (start ... stop).each do |pos|
- self.bit_unset(pos)
+ 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
+
+ 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.
def test_interval_set_with_bad_interval_raises
assert_raise(BitArrayError) { @ba.interval_set(-1, 4) }
- assert_raise(BitArrayError) { @ba.interval_set(1, 14) }
+ assert_raise(BitArrayError) { @ba.interval_set(1, 10) }
assert_raise(BitArrayError) { @ba.interval_set(4, 2) }
end
def test_interval_set_returns_correctly
- @ba.interval_set(1, 9)
-
- assert_equal("0111111110", @ba.to_s)
+ @ba.interval_set(0, 0)
+ assert_equal("1000000000", @ba.to_s)
+ @ba.interval_set(9, 9)
+ assert_equal("1000000001", @ba.to_s)
+ @ba.interval_set(2, 7)
+ assert_equal("1011111101", @ba.to_s)
+ @ba.interval_set(1, 8)
+ assert_equal("1111111111", @ba.to_s)
end
def test_interval_unset_with_bad_interval_raises
assert_raise(BitArrayError) { @ba.interval_unset(-1, 4) }
- assert_raise(BitArrayError) { @ba.interval_unset(1, 14) }
+ assert_raise(BitArrayError) { @ba.interval_unset(1, 10) }
assert_raise(BitArrayError) { @ba.interval_unset(4, 2) }
end
def test_interval_unset_returns_correctly
~@ba
- @ba.interval_unset(1, 9)
- assert_equal("1000000001", @ba.to_s)
+ @ba.interval_unset(0, 0)
+ assert_equal("0111111111", @ba.to_s)
+ @ba.interval_unset(9, 9)
+ assert_equal("0111111110", @ba.to_s)
+ @ba.interval_unset(2, 7)
+ assert_equal("0100000010", @ba.to_s)
+ @ba.interval_unset(1, 8)
+ assert_equal("0000000000", @ba.to_s)
end
def test_each_interval_returns_correctly