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");
|