in reply to Re^8: Locating a specified number of contiguous 0 bits within a large bitstring efficiently.
in thread Locating a specified number of contiguous 0 bits within a large bitstring efficiently.

ok, well, here's a version that does all $N. The one caveat is it doesn't necessarily return the first match, the main problem with the (or at least my) regexp approach being that when you have a bunch of '|' alternatives and more than one matches, you can't control which one gets used.

Anyway, here's the code:

use strict; use warnings; no warnings 'redefine'; # $cc[$n]->[$k] is a character class matching a byte with # a run of zero bits of length at least $k and starting # exactly $n bits from the end our @cc = map { my $n = $_; [ ($n==0 ? () : $n==8 ? ('') : (undef)), map { # $m = first bit after the start of the run # that does not have to be zero my $m = $_+8-$n; local $" = ''; qr{[@{[map { quotemeta(chr(0x80>>$n|$_<<$m)) . ($n<7 ? '-' . quotemeta(chr(0xFF>>$n|$_<<$m)) : '') } 0..(0xFF>>$m)]}]} } ($n==0 ? 0 : 1)..$n ] } 0..8; $cc[0]->[0] = qr{^|$cc[0]->[0]"}; sub zero_bit_regexp { my $N = shift; my $p = join '|', map { $N<=$_ ? "$cc[$_]->[$N]()" : "$cc[$_]->[$_](\\0{@{[($N-$_)>>3]}}$cc[8]->[($N-$ +_)&0x7])" } 0..7; return qr{$p}; } sub match_0s_w { my $N = shift; # number of consecutive '0' bits to be mat +ched local $_ = shift || $_; # string to match against return ($_ !~ zero_bit_regexp($N)) ? -1 : $-[$#-]*8 - $#- + 1 }
which gives
1: 0 2: 5 3: 5 4: 14 5: 14 6: 20 7: 27 8: 35 9: 44 10: 54 11: 65 12: 77 13: 90 14: 119 15: 119 16: 135 17: -1
where the results for 2, 4, and 14 are technically correct but unexpected
  • Comment on Re^9: Locating a specified number of contiguous 0 bits within a large bitstring efficiently.
  • Select or Download Code