Re: bit pattern to bit position mapping
by grinder (Bishop) on Nov 19, 2006 at 10:01 UTC
|
sub b2i {
return split //, unpack('b*', @_);
}
This also obviates the need to determine whether it is a 32-bit or 64-bit quantity. You'll may get a number of zeros at the end of the array. You could clip the unnecessary zeros before splitting into values with:
sub b2i {
my $bitstring = unpack('b*', @_);
$bitstring =~ s/0+$//;
return split //, $bitstring;
}
• another intruder with the mooring in the heart of the Perl
| [reply] [d/l] [select] |
|
|
I'm after the positions of the set bits, not the bits themselves.
Please see the comment in the code sample for what I mean.
| [reply] |
|
|
I'm after the positions of the set bits
Ah so sorry, I left that as an exercise for the reader. All you have to do is run through the array of 0,1 values, and push the offset to another array if the value is 1. Then return that array. Which goes something like (untested)
sub set_bit_offsets {
my @bitmap = split //, unpack('b*', @_);
my @offset;
for my $off (0..$#bitmap) {
if ($bitmap[$off] == 1) {
push @offset, $off;
}
}
return @offset;
}
In terms of efficiency, yes, that could be written as a one-liner. That would be something like:
sub set_bit_offsets {
my @bitmap = split //, unpack('b*', @_);
return grep {$bitmap[$_]} 0..$#bitmap;
}
• another intruder with the mooring in the heart of the Perl
| [reply] [d/l] [select] |
|
|
|
|
Re: bit pattern to bit position mapping
by jonadab (Parson) on Nov 19, 2006 at 13:36 UTC
|
I take it you've profiled your application, which is experiencing noticeable performance issues, and determined that it's spending a lot of its time in this subroutine? Of course you have, and it's silly of me to even ask. Obviously you profiled your application, because you wouldn't otherwise be asking for a faster way to do this little thing, because you know full well that premature optimization is a root of all kinds of evil, for which some, having strayed, have pierced themselves through with many sorrows. You know this, and therefore you are only asking about a faster way to code this particular subroutine because you have established that its speed actually matters. Right? Right?
Sanity? Oh, yeah, I've got all kinds of sanity. In fact, I've developed whole new kinds of sanity. You can just call me "Mister Sanity". Why, I've got so much sanity it's driving me crazy.
| [reply] |
|
|
| [reply] |
|
|
it is currently consuming 14% of the total runtime
oh, well why didn't you say so in the first place? Rewrite the hot function in C, and use array references, to stop slinging memory around.
use strict;
use Inline C => <<'__C_CODE__';
SV*
b2i(int value) {
AV *out;
int i;
out = (AV *)sv_2mortal((SV *)newAV());
i = 0;
while (value > 0) {
if (value & 1)
av_push(out, newSViv(i));
++i;
value >>= 1;
}
return((SV *)newRV((SV *)out));
}
__C_CODE__
my $ridx = b2i(12345);
print "@$ridx\n";
What does that do to the run time?
• another intruder with the mooring in the heart of the Perl
| [reply] [d/l] |
|
|
|
|
| [reply] |
|
|
| [reply] |
Re: bit pattern to bit position mapping
by traveler (Parson) on Nov 19, 2006 at 17:06 UTC
|
I suggest getting rid of the function code and inlining the grep. This saves the overhead of the function call, at least. You could use -P or your favorite macro processor to make it look like a function call. | [reply] [d/l] |