Algorithm-BitVector
view release on metacpan or search on metacpan
lib/Algorithm/BitVector.pm view on Meta::CPAN
} else {
$run = '1';
}
my @bitlist = split //, "$self";
shift @bitlist;
foreach my $bit (@bitlist) {
if (($bit == 0) && ($previous_bit == 0)) {
$run .= '0';
} elsif (($bit == 1) && ($previous_bit == 0)) {
push @allruns, $run;
$run = '1';
} elsif (($bit == 0) && ($previous_bit == 1)) {
push @allruns, $run;
$run = '0';
} else {
$run .= '1';
}
$previous_bit = $bit;
}
push @allruns, $run;
return @allruns
}
## This method returns the "canonical" form of a BitVector instance that is obtained by
## circularly rotating the bit pattern through all possible shifts and returning the
## pattern with the maximum number of leading zeros. This is also the minimum int value
## version of a bit pattern. This method is useful in the "Local Binary Pattern"
## algorithm for characterizing image textures. If you are curious as to how, see my
## tutorial on "Measuring Texture and Color in Images."
sub min_canonical {
my $self = shift;
my @intvals_for_circular_shifts = map {int($self << 1)} 0 .. $self->length();
my $min_int_val = min @intvals_for_circular_shifts;
return Algorithm::BitVector->new( intVal => $min_int_val, size => $self->length() );
}
## Check if the integer value of the bitvector is a prime through the Miller-Rabin
## probabilistic test of primality. If not found to be a composite, estimate the
## probability of the bitvector being a prime using this test.
sub test_for_primality {
my $p = int(shift);
die "\nThe primality test method test_for_primality() is intended for only " .
"small integers --- integers that are relatively small in relation to " .
"the largest integer that can fit Perl's 4-byte int representation:$!"
if $p > 0x7f_ff_ff_ff;
return "is NOT a prime" if $p == 1;
my @probes = (2,3,5,7,11,13,17);
foreach my $a (@probes) {
return "is a prime" if $a == $p;
}
return "is NOT a prime" if any {$p % $_ == 0} @probes;
my ($k, $q) = (0, $p-1);
while (! ($q & 1)) {
$q >>= 1;
$k++;
}
foreach my $a (@probes) {
my $a_raised_to_q = _powmod_small_ints($a, int($q), $p);
next if $a_raised_to_q == 1 or $a_raised_to_q == $p - 1;
my $a_raised_to_jq = $a_raised_to_q;
my $primeflag = 0;
foreach my $j (0..$k-1) {
$a_raised_to_jq = _powmod_small_ints($a_raised_to_jq, 2, $p);
if ($a_raised_to_jq == $p-1) {
$primeflag = 1;
last;
}
}
return "is NOT a prime" unless $primeflag;
}
my $probability_of_prime = 1 - 1.0/(4 ** @probes);
return "is a prime with probability $probability_of_prime";
}
## This routine is for modular exponentiation of small integers, meaning the
## integers that can be accommodated (before and after exponentiation) in the native
## 4-byte int representation. For larger integers, a call to this function should
## be replaced by a call to modular exponentiation of the Math::BigInt module.
sub _powmod_small_ints {
my $base = shift;
my $exponent = shift;
my $mod = int(shift);
warn "This is just a warning: The modular exponentiation method is not meant for very large numbers (IMPORTANT: This is just a very rough check on the size of the numbers involved)"
if any {$_ > 0x0f_ff_ff_ff} (int($base), int($exponent), int($mod));
my $result = 1;
my $a = int($base);
my $b = $exponent;
while (int($b) > 0) {
$result = ($result * $a) % $mod if int($b) & 1;
$b = $b >> 1;
$a = ($a * $a) % $mod;
}
return $result;
}
## This method is for a generating a bit pattern of a given size with random bits.
sub gen_random_bits {
my $self = shift;
my $width = shift;
my $candidate_bits = "0b" . join '', Math::Random::random_uniform_integer($width, 0, 1);
my $candidate = oct $candidate_bits;
$candidate |= 1;
$candidate |= (1 << $width-1);
$candidate |= (2 << $width-3);
return Algorithm::BitVector->new( intVal => $candidate );
}
sub length {
my $self = shift;
return $self->{size};
}
sub _check_for_illegal_params {
my @params = @_;
my @legal_params = qw / filename
size
intVal
bitlist
bitstring
hexstring
textstring
/;
my $found_match_flag;
foreach my $param (@params) {
foreach my $legal (@legal_params) {
$found_match_flag = 0;
if ($param eq $legal) {
$found_match_flag = 1;
last;
}
}
last if $found_match_flag == 0;
}
return $found_match_flag;
}
1;
=pod
=head1 NAME
Algorithm::BitVector --- A memory efficient packed representation of arbitrary sized
bit arrays and for logical and arithmetic operations on such arrays.
=head1 SYNOPSIS
use Algorithm::BitVector;
# Constructing a given sized bitvector of all zeros:
$bv = Algorithm::BitVector->new( size => 7 );
print "$bv\n"; # 0000000
# Constructing a bitvector whose integer value is specified:
$bv = Algorithm::BitVector->new( intVal => 123456 );
print "$bv\n"; # 11110001001000000
print int($bv); # 123456
# Constructing a bitvector from a very large integer:
use Math::BigInt;
$x = Math::BigInt->new('12345678901234567890123456789012345678901234567890');
$bv = Algorithm::BitVector->new( intVal => $x );
# Constructing a bitvector from a given bit string:
$bv = Algorithm::BitVector->new( bitstring => '00110011' );
# Constructing a bitvector from an ASCII text string:
$bv = Algorithm::BitVector->new( textstring => "hello\njello" );
# Constructing a bitvector from a hex string:
$bv = Algorithm::BitVector->new( hexstring => "68656c6c6f" );
# Constructing a bitvector from a bit list passed as an anonymous array:
$bv = Algorithm::BitVector->new( bitlist => [1, 1, 0, 1] );
# Constructing a bitvector from the contents of a disk file:
$bv = Algorithm::BitVector->new( filename => 'testinput.txt' );
$bv1 = $bv->read_bits_from_file(64); # bitvector from the first 64 bits
# and so on
=head1 CHANGES
Version 1.26 incorporates the following changes: (1) It allows you to carry out
slice-based set and get operations on a BitVector object. The two new methods for
these operations are named C<get_slice()> and C<set_slice()>. (2) It includes a new
method named C<min_canonical()> that returns a circularly rotated version of a
BitVector with the least integer value. For obvious reasons, this version would also
have the largest number of leading zeros. And (3) It fixes a bug in the
implementation of the method C<gf_divide_by_modulus()>.
Version 1.25 incorporates bugfix for the case when you try to construct a bitvector
of a specified length from a large integer that is supplied to the module constructor
( run in 1.048 second using v1.01-cache-2.11-cpan-ceb78f64989 )