Version 2 of Bit Twiddling

Updated 2013-12-02 18:04:52 by pooryorick

1-Bits in a positive int

count the number of bits of value 1 in an integer

(sign-extended for negatives, so better use positives only):

proc nbits n {
    set f [format %X $n]
    set res 0
    foreach nybble {0 1 2 3 4 5 6 7 8 9 A B C D E F} \
        bits   {0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4} {
        set res [expr $res+$bits*[regsub -all $nybble $f - -]]
    }
    set res
} ;# RS

More than 30 times faster, and works for negative numbers too:

proc popcount { i } { # count the population of ones in the integer i
    set pop 0
    while { $i != 0 } {
        incr pop
        set i [expr { $i & ( $i - 1 ) }]
    }
    return $pop
} ;# kbk [http://titania.crd.ge.com/people/kennykb.html]

This one is slower than the last, but it's a one-liner:

proc nbits2 n {
    expr 0[string map {0 +0 1 +1 2 +1 3 +2 4 +1 5 +2 6 +2 7 +3 8 +1 9 +2 A +2 B +3 C +2 D +3 E +3 F +4} [format %X $n]]
}

Iterate over an IP address Range

kbk pasted this

set spec 192.168.1.0/28
regexp {(\d+)[.](\d+)[.](\d+)[.](\d+)/(\d+)} $spec -> b0 b1 b2 b3 size
set quad [expr {($b0 << 24) | ($b1 << 16) | ($b2 << 8) | $b3}]
for {set i 0} {$i < (1<<(32-$size))} {incr i} {
        set q2 [expr {$quad + $i}]
        set result [expr {$q2 & 0xff}]
        for {set j 0} {$j < 3} {incr j} {
                set q2 [expr {$q2 >> 8}]
                set result [expr {$q2 & 0xff}].$result
        }
                puts $result
} 

from a paste by kbk

See Also