1 # Copyright (C) 2007-2011 Martin A. Hansen.
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # http://www.gnu.org/copyleft/gpl.html
19 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
21 # This software is part of the Biopieces framework (www.biopieces.org).
23 # >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
29 # Error class for all exceptions to do with BitArray.
30 class BitArrayError < StandardError; end
32 # Class containing methods for creating and manipulating a bit array.
34 attr_accessor :byte_array
37 # Method to initialize a new bit array of a given size in bits.
40 @byte_array = init_byte_array
41 @count_array = init_count_array
44 # Method that sets all bits in the bit array.
46 self.byte_array.fill!(~0)
51 # Method that unsets all bits in the bit array.
53 self.byte_array.fill!(0)
58 # Method to set a bit to 1 at a given position in the bit array.
60 raise BitArrayError, "Position #{pos} must be an integer." unless pos.is_a? Fixnum
61 raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size}" unless (0 ... @size ).include? pos
63 @byte_array[byte_pos(pos)] = @byte_array[byte_pos(pos)] | bit_pos(pos)
66 # Method to set a bit to 0 at a given position in the bit array.
68 raise BitArrayError, "Position #{pos} must be an integer." unless pos.is_a? Fixnum
69 raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size}" unless (0 ... @size ).include? pos
74 @byte_array[byte_pos(pos)] = @byte_array[byte_pos(pos)] & mask
77 # Method to check if a bit at a given position in the bit array is set.
79 raise BitArrayError, "Position #{pos} must be an integer." unless pos.is_a? Fixnum
80 raise BitArrayError, "Position #{pos} outside of range: 0 ... #{@size}" unless (0 ... @size ).include? pos
82 (@byte_array[byte_pos(pos)] & bit_pos(pos)) != 0
85 # Method that returns the number of bits set "on" in a bit array.
89 self.byte_array.each do |byte|
90 bits_on += @count_array[byte]
96 # Method that returns the number of bits set "off" in a bit array.
101 # Method to run bitwise AND (&) on two bit arrays and return the
102 # result in the first bit array. Bits are copied if they exists in BOTH operands.
103 # 00111100 & 00001101 = 00001100
105 raise BitArrayError, "uneven size of bit arrays: #{self.size} != #{ba.size}" if self.size != ba.size
107 self.byte_array = self.byte_array & ba.byte_array
112 # Method to run bitwise OR (|) on two bit arrays and return the
113 # result in the first bit array. Bits are copied if they exists in EITHER operands.
114 # 00111100 | 00001101 = 00111101
116 raise BitArrayError, "uneven size of bit arrays: #{self.size} != #{ba.size}" if self.size != ba.size
118 self.byte_array = self.byte_array | ba.byte_array
123 # Method to run bitwise XOR (^) on two bit arrays and return the
124 # result in the first bit array. Bits are copied if they exists in ONE BUT NOT BOTH operands.
125 # 00111100 ^ 00001101 = 00110001
127 raise BitArrayError, "uneven size of bit arrays: #{self.size} != #{ba.size}" if self.size != ba.size
129 self.byte_array = self.byte_array ^ ba.byte_array
134 # Method to flip all bits in a bit array. All set bits become unset and visa versa.
136 self.byte_array = ~(self.byte_array)
141 # Method to convert a bit array to a string.
145 (0 ... @size).each do |pos|
156 alias :to_string :to_s
160 # Method to initialize the byte array (string) that constitutes the bit array.
162 raise BitArrayError, "Size must be an integer, not #{@size}" unless @size.is_a? Fixnum
163 raise BitArrayError, "Size must be positive, not #{@size}" unless @size > 0
165 NArray.byte(((@size - 1) / BitsInChar) + 1)
168 # Method that returns an array where the element index value is
169 # the number of bits set for that index value.
173 (0 ... (2 ** BitsInChar)).each do |i|
174 count_array << bits_in_char(i)
180 # Method that returns the number of set bits in a char.
181 def bits_in_char(char)
184 (0 ... BitsInChar).each do |pos|
185 bits += 1 if ((char & bit_pos(pos)) != 0)
191 # Method that returns the byte position in the byte array for a given bit position.
196 # Method that returns the bit position in a byte.
198 1 << (BitsInChar - 1 - (pos % BitsInChar))