Algorithm-BitVector
view release on metacpan or search on metacpan
lib/Algorithm/BitVector.pm view on Meta::CPAN
$self->{size} = scalar @{$self->{bitlist}};
} elsif (defined $self->{bitstring}) {
die "When using the `bitstring' option in the constructor call, you cannot use any " .
"other option at the same time: $!"
if $self->{filename} or $self->{intVal} or $self->{size}
or $self->{bitlist} or $self->{hexstring} or $self->{textstring};
my @bitlist_from_bitstring = split //, $self->{bitstring};
$self->{bitlist} = \@bitlist_from_bitstring;
$self->{size} = scalar @{$self->{bitlist}};
} elsif (defined $self->{textstring}) {
die "When using the `textstring' option in the constructor call, you cannot use any " .
"other option at the same time: $!"
if $self->{filename} or $self->{intVal} or $self->{size}
or $self->{bitlist} or $self->{hexstring} or $self->{bitstring};
my $bitstring_from_text = join '', map {length($_) == 8 ? $_
: ('0' x (8 - length($_))) . $_} map {sprintf "%b", $_}
map ord, split //, $self->{textstring};
my @bitlist_from_text = split //, $bitstring_from_text;
$self->{bitlist} = \@bitlist_from_text;
$self->{size} = scalar @{$self->{bitlist}};
} elsif (defined $self->{hexstring}) {
die "When using the `hexstring' option in the constructor call, you cannot use any " .
"other option at the same time: $!"
if $self->{filename} or $self->{intVal} or $self->{size}
or $self->{bitlist} or $self->{textstring} or $self->{bitstring};
my $bitstring_from_hex = join '', map {length($_) == 4 ? $_
: ('0' x (4 - length($_))) . $_} map {sprintf "%b", $_}
map {hex $_} split //, $self->{hexstring};
my @bitlist_from_hex = split //, $bitstring_from_hex;
$self->{bitlist} = \@bitlist_from_hex;
$self->{size} = scalar @{$self->{bitlist}};
}
my $shorts_needed = int( (@{$self->{bitlist}} + 15) / 16 );
@{$self->{_vector}} = map {unpack "n", pack("n", 0)} 0 .. $shorts_needed-1;
my @interleaved = (0..$self->{size}-1, @{$self->{bitlist}})
[map {$_,$_+$self->{size}} (0 .. $self->{size}-1)];
pairmap {$self->set_bit($a,$b)} @interleaved;
$self->{bitlist} = undef;
return $self;
}
## Set the bit at the designated position to the value shown
sub set_bit {
my $self = shift;
my $posn = shift;
my $val = shift;
croak "incorrect value for a bit" unless $val =~ /\d/ && ($val == 0 or $val == 1);
die "index range error" if ($posn >= $self->{size}) or ($posn < - $self->{size});
$posn = $self->{size} + $posn if $posn < 0;
my $block_index = int($posn / 16);
my $shift = $posn & 0xF;
my $cv = $self->{_vector}->[$block_index];
if ( ( ( $cv >> $shift ) & 1 ) != $val) {
$self->{_vector}->[$block_index] = $cv ^ (1 << $shift);
}
}
## Get the bit from the designated position. This method can also return a slice of a
## bitvector. HOWEVER, NOTE THAT THE SLICE IS RETURNED AS A LIST OF THE BITS IN THE
## INDEX RANGE YOU SPECIFIED. You can either easily convert the list of bits returned
## into a bitvector in your own code or, starting with Version 1.26, you can call the
## get_slice() method.
sub get_bit {
my $self = shift;
my $pos = shift;
unless (ref($pos) eq "ARRAY") {
die "index range error" if ($pos >= $self->{size}) or ($pos < - $self->{size});
$pos = $self->{size} + $pos if $pos < 0;
return ( $self->{_vector}->[int($pos/16)] >> ($pos&15) ) & 1;
}
# my @slice = map $self->get_bit($_), (@$pos)[0..@$pos-1];
my @slice = map $self->get_bit($_), (@$pos)[0..@$pos-2];
return \@slice;
}
## Get the slice of bits from the bitvector corresponding to the index range specified
## by the argument. The slice is returned as an instance of Algorithm::BitVector
sub get_slice {
my $self = shift;
my $index_range = shift;
my $slice_bv = Algorithm::BitVector->new( size => @$index_range - 1 );
map $slice_bv->set_bit($_ - $index_range->[0], $self->get_bit($_)), @$index_range[0..@$index_range-2];
return $slice_bv;
}
## Set a slice of a BitVector from the bits in the argument BitVector object:
sub set_slice {
my $self = shift;
my $index_range = shift;
my $values_bv = shift;
die "the width of the index range for slice setting does not equal the size of the values array"
unless @$index_range - 1 == $values_bv->length();
# unless @$index_range == $values_bv->length();
map $self->set_bit($_, $values_bv->get_bit($_ - $index_range->[0])), @$index_range[0..@$index_range-2];
}
## Overloading of the string conversion operator. Return the string representation
## of a bitvector.
sub _str {
my $self = shift;
return join '', map $self->get_bit($_), 0 .. $self->{size}-1;
}
## Overloading of the `+' operator. Concatenate the argument bitvectors. Return the
## concatenated bitvector as a new BitVector instance.
sub _join {
my ($bv1, $bv2) = @_;
croak "Abort: The concatenation operator invoked with either undefined " .
"or wrong types of operands: $!"
unless UNIVERSAL::isa( $bv1, 'Algorithm::BitVector') and
UNIVERSAL::isa( $bv2, 'Algorithm::BitVector');
my $allbits = $bv1->_str() . $bv2->_str();
return Algorithm::BitVector->new( bitstring => $allbits );
}
sub _compare {
my ($bv1, $bv2) = @_;
croak "Abort: The comparison operator invoked with either undefined " .
"or wrong types of operands: $!"
unless UNIVERSAL::isa( $bv1, 'Algorithm::BitVector') and
UNIVERSAL::isa( $bv2, 'Algorithm::BitVector');
( run in 1.625 second using v1.01-cache-2.11-cpan-97f6503c9c8 )