diff --git a/lib/bitarray-array.rb b/lib/bitarray-array.rb index 7988fa8..2191ffb 100644 --- a/lib/bitarray-array.rb +++ b/lib/bitarray-array.rb @@ -3,7 +3,7 @@ class BitArray attr_reader :field include Enumerable - VERSION = "1.2.0" + VERSION = "1.3.0" ELEMENT_WIDTH = 32 def initialize(size, field = nil) @@ -43,8 +43,9 @@ def each_byte end # Returns the total number of bits that are set - # (The technique used here is about 6 times faster than using each or inject direct on the bitfield) + # Use Brian Kernighan's way, see + # https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan def total_set - @field.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a } + @field.each_byte.inject(0) { |a, byte| (a += 1; byte &= byte - 1) while byte > 0 ; a } end end diff --git a/lib/bitarray.rb b/lib/bitarray.rb index ebfe269..992d753 100644 --- a/lib/bitarray.rb +++ b/lib/bitarray.rb @@ -3,7 +3,7 @@ class BitArray attr_reader :field include Enumerable - VERSION = "1.2.0" + VERSION = "1.3.0" def initialize(size, field = nil, reverse_byte: true) @size = size @@ -47,9 +47,10 @@ def each_byte end # Returns the total number of bits that are set - # (The technique used here is about 6 times faster than using each or inject direct on the bitfield) + # Use Brian Kernighan's way, see + # https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan def total_set - @field.bytes.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a } + @field.each_byte.inject(0) { |a, byte| (a += 1; byte &= byte - 1) while byte > 0 ; a } end def byte_position(position) diff --git a/test/test_bitarray.rb b/test/test_bitarray.rb index 3a3c334..157453c 100644 --- a/test/test_bitarray.rb +++ b/test/test_bitarray.rb @@ -1,5 +1,5 @@ require "minitest/autorun" -require "bitarray" +require_relative "../lib/bitarray" class TestBitArray < Minitest::Test def setup