Version 0 of Bit vectors

Updated 2002-05-06 06:51:54

Richard Suchenwirth 2002-05-05 - Here is a routine for querying or setting single bits in vectors, where bits are addressed by non-negative integers. Implementation is as a "little-endian" list of integers, where bits 0..31 are in the first list element, 32..63 in the second, etc.

USAGE

 bit varName position ?bitval?

If bitval is given, sets the bit at numeric position position to 1 if bitval != 0, else to 0; in any case returns the bit value at specified position. If variable varName does not exist in caller's scope, it will be created; if it is not long enough, it will be extended to hold at least $position+1 bits, e.g. bit foo 32 will turn foo into a list of two integers, if it was only one before. All bits are initialized to 0.

 proc bit {varName pos {bitval {}}} {
    upvar 1 $varName var
    if {![info exist var]} {set var 0}
    set element [expr {$pos/32}]
    while {$element >= [llength $var]} {lappend var 0}
    set bitpos [expr {$pos%32}]
    set word [lindex $var $element]
    if {$bitval != ""} {
        if {$bitval} {
            set word [expr {$word | 1 << $bitpos}]
        } else {
            set word [expr {$word & ~(1 << $bitpos)}]
        }
        set var [lreplace $var $element $element $word]
    }
    expr {($word & 1 << $bitpos) != 0}
 }

#---------------------- now testing...

 if {[file tail [info script]] == [file tail $argv0]} {
    foreach {test      expected} {
        {bit foo 5 1}  1
        {set foo}      32
        {bit foo 32 1} {32 1}
    } {
        catch {eval $test} res
        puts $test:$res/$expected
    }
 }

if 0 {Discussion: This may be used for Boolean properties of numerically indexed sets of items. Example: An existence map of ZIP codes between 00000 and 99999 can be kept in a list of 3125 integers (where each element requires about 15 bytes overall), while implementing the map as an array would take 100000 * 42 bytes in worst case, but still more than a bit vector if the population isn't extremely sparse - in that case, a list of 1-bit positions, retrieved with lsearch, might be more efficient in memory usage. Runtime of bit vector accesses is constant, except when a vector has to be extended to much larger length.

Bit vectors can also be used to indicate set membership (set operations would run faster if processing 32 bits on one go with bitwise operators (&, |, ~, ^)) - or pixels in a binary imary image, where each row could be implemented by a bitvector.


Category Concept | Arts and crafts of Tcl-Tk programming