in reply to Most Significant Set Bit

Perhaps I misunderstood what clz() does, but does the code you posted really work? It gives me 8 for $z=17. Shouldn't it be 27 for 32bit and 59 for 64bit? 17=10001 (with 59 leading zeros and MSB is at the zeros-side, left)

Replies are listed 'Best First'.
Re^2: Most Significant Set Bit
by coldr3ality (Acolyte) on Mar 20, 2024 at 23:03 UTC
    It actually returns an integer with one bit set: the bit to the right of the MSSB. I overlooked this modification when I posted the code. Another modification is that it will not return less than 2. I may have to edit in an unmodified version to fix the original post. The modification is part of the aforementioned binary search variant I'm experimenting with, and I meant to leave that out.

    Given the leftmost / most significant bit is #0, the original code is equivalent to:
    my $z=17; my $m= $z<4? 2: 1<<( 63-( clz($z) +1) ); # 64-bit system integer my $m= $z<4? 2: 1<<( 31-( clz($z) +1) ); # 32-bit system integer




    EDIT 2024/3/27
    I know the original point is moot, but there is always the possibility that a future project will benefit from this idea somehow, and writing these binary chop statements by hand is precarious. The below code generator makes short work of it. Any power-of-2 from 2 to 64 will work as long as your system supports integers that size. 128 and 256 should work as well. Higher powers-of-2 will need a larger bitvector than the one I assigned to $BinFlow.



    EDIT 2024/3/30: more comprehensible variable names and comments
    use strict; use warnings; #### BINARY CHOP GENERATOR #### This script generates a single Perl statement #### in the form of a tree of inline conditionals #### to find the count of leading zeros in an integer $z #### with bit width P2 in log(P2)/log(2) steps. #### #### Disclaimer: for a better solution, use GCC::Builtins qw(clz). #configuration use constant Tab => ' 'x4; # tab width use constant P2 => 64; # bit width # (2, 4, 8, 16, 32, 64, 128, 256) use constant nSteps => (log(P2)/log(2) ); use constant MaxInt => (1<< P2)-1 ; use constant MASK_0 => 1<<(P2 -1); use constant CASE_0_LS => P2 -1; my $BinFlow= pack('C9', (0)x9); # bitvector of iterators carries # the binary composition forward # as the loop scales the tree, # printing it line by line. my $B=1; my $ls_=0; # supporting conditional's running left-shift my $ls=$ls_+(P2>>1); # "this" conditional's running left-shift print('my $m=',sprintf('0x%X', MaxInt&( -(1<<($ls-1)) )),'&$z? '); while($B>0){ my $if_else=vec($BinFlow, $B, 2)++; #advance conditional $B if($if_else==0){ #BEGIN NEW CONDITIONAL #(the "if" part) if($B<nSteps){ #not the final step yet? $ls_=vec( $BinFlow,++$B, 8)=$ls; #set left-shift as of $B $ls+= P2 >>$B; print("\r\n", Tab x$B); printf('0x%X&$z? ', MaxInt&( -(1<<($ls-1)) ) ); }else{ # To delineate all 65 unique conditional flow paths, # the 0th and 1st paths require an additional step. # These are treated as the most unlikely cases. printf("\r\n".(Tab x($B+1)). '0x%X&$z? 0'. "\r\n".( Tab x$B). ':'. (' 'x(8+((log(MASK_0)/log(16))>>0))), MASK_0 ) if $ls==CASE_0_LS; print(1+P2-(P2>>$B)-$ls, ': ', 1+P2-$ls, "\n"); vec( $BinFlow, $B, 2)=0; #reset step $B. $ls=$ls_; #revert left-shift and $ls_=vec( $BinFlow,--$B, 8); #fall back to previous step. } }elsif($if_else==1){ #RESUME CONDITIONAL #(the "else" part) print( Tab x$B); $ls_=$ls; ++$B; #climb back up a step $ls-= P2 >>$B; #negate shift component B printf(': 0x%X&$z? ', MaxInt&( -(1<<($ls-1)) ) ); }else{ #END CONDITIONAL vec( $BinFlow, $B, 2)=0; #reset step $B. $ls=$ls_; #revert left-shift and $ls_=vec( $BinFlow,--$B, 8); #fall back to previous step. } } print(";\r\n");