Difference between revisions of "Talk:Ruby bitfield"

From RogueBasin
Jump to navigation Jump to search
 
Line 5: Line 5:
Note that <tt>clear_all()</tt> and <tt>set_all</tt> are practically instantaneous. :)
Note that <tt>clear_all()</tt> and <tt>set_all</tt> are practically instantaneous. :)


SPB 7/8/2010 - Note that this implementation is *wrong*.  If you call clear on a bit thats already cleared, it would end up being set!  You need to bitwise and against the complement...
SPB 7/8/2010 - Note that this implementation is *wrong*.  If you call clear on a bit thats already cleared, it would end up being set!   
 
This works:
value == 0 ? @field ^= @field[position] << position : @field |= 1 << position





Latest revision as of 19:00, 8 July 2010

It's a nice example, but why wouldn't you just use an Integer (an actual bitfield) rather than an Array or String? Using actual bit operations on an Integer seems more straightforward... I'll see about setting up some timing tests to compare speed.

Here's a fairly clean conversion of your class (with minor modifications). Note that clear_all() and set_all are practically instantaneous. :)

SPB 7/8/2010 - Note that this implementation is *wrong*. If you call clear on a bit thats already cleared, it would end up being set!

This works: value == 0 ? @field ^= @field[position] << position : @field |= 1 << position


class BitField
  include Enumerable
  attr_reader :size

  def initialize(size)
    @size = size
    @field = 0
  end

  def []=(position,value)
    value == 0 ? @field ^= 1 << position : @field |= 1 << position
  end

  def set(position)
    self[position] = 1
  end

  def clear(position)
    self[position] = 0
  end

  def [](position)
    @field[position]
  end
  def is_set?(position)
    @field[position] == 1
  end

  def each(&block)
    @size.times { |position| yield @field[position] }
  end

  def are_set
    @result = Array.new
    @size.times { |position| self.is_set?(position) and @result << position }
    return @result
  end

  def to_s
    return inject("") { |string,position| string + position.to_s }
  end

  def clear_all
    @field = 0
  end

  def set_all
    @field = (2 ** (@size+1)) -1
  end
end