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 )