Algorithm-BitVector

 view release on metacpan or  search on metacpan

lib/Algorithm/BitVector.pm  view on Meta::CPAN

              '&'        =>    '_and',
              '^'        =>    '_xor',
              '<=>'      =>    '_compare',
              '<<'       =>    '_lshift',
              '>>'       =>    '_rshift',
              '<>'       =>    '_iter',
              'fallback' =>    1;

sub _readblock {
    my $blocksize = shift;
    my $bitvector = shift;
    my $block;
    my $more_to_read;
    my $i = 0;
    my $byte_as_bits;
    my $bitstring = '';
    while ( $i < $blocksize / 8 ) {
        $i++;
        my $num_bytes_read = sysread($bitvector->{FILEIN}, my $byte, 1);
        unless ($num_bytes_read) {
            if (length($bitstring) < $blocksize) { 
                $bitvector->{more_to_read} = 0;
                $more_to_read = 0;
            }
            return $bitstring;
        } else {
            my $bits_as_string = sprintf "%vb", $byte;
            $bits_as_string = '0' x (8 - length($bits_as_string)) . $bits_as_string;
            $bitstring .= $bits_as_string;
        }
    }
    my $file_pos = tell $bitvector->{FILEIN};
    # peek at the next byte; moves file position only if a
    # byte is read
    my $num_bytes_read = sysread($bitvector->{FILEIN}, my $next_byte, 1);
    if ($num_bytes_read) {
        # pretend we never read the byte
        sysseek $bitvector->{FILEIN}, $file_pos - 1, SEEK_CUR;
    } else {
        $bitvector->{more_to_read} = 0;
    }
    return $bitstring;
}

# Constructor:
sub new { 
    my ($class, %args) = @_;
    my @params = keys %args;
    croak "\nYou have used a wrong name for a keyword argument " .
          "--- perhaps a misspelling\n" 
          if _check_for_illegal_params(@params) == 0;
    my $self = {
        filename                          =>   $args{filename},
        size                              =>   $args{size},
        intVal                            =>   $args{intVal},
        bitlist                           =>   $args{bitlist},
        bitstring                         =>   $args{bitstring},
        hexstring                         =>   $args{hexstring},
        textstring                        =>   $args{textstring},
    };
    bless $self, $class;
    if ( $self->{filename} )  {
        die "When using the `filename' option in the constructor call, you cannot use any " .
            "other option at the same time: $!" 
            if $self->{intVal} or $self->{size} or $self->{bitlist} 
               or $self->{bitstring} or $self->{hexstring} or $self->{textstring};
        open $self->{FILEIN}, "< $self->{filename}" 
                            or die "unable to open file $self->{filename}: $!";
        $self->{more_to_read} = 1;
        return $self;
    } elsif ( defined $self->{intVal} )  {
        die "When using the `intVal' option in the constructor call, you CANNOT use `filename', " .
            "`bitlist', 'bitstring', `hexstring', or `textstring' options: $!" 
            if $self->{filename}  or $self->{bitlist} or $self->{bitstring} 
               or $self->{hexstring} or $self->{textstring};
        if ($self->{intVal} == 0 && ! defined $self->{size}) {
            $self->{bitlist} = [0];
            $self->{size} = 1;
        } else {
            my @bitarray;
#            if (ref($self->{intVal}) eq 'Math::BigInt') {
            if (ref($self->{intVal}) eq 'Math::BigInt' && ! defined $self->{size}) {
                my $bitlist_str = $self->{intVal}->as_bin();
                $bitlist_str =~ s/^0b//;
                @bitarray = split //, $bitlist_str;
            } elsif (ref($self->{intVal}) eq 'Math::BigInt' && defined $self->{size}) {   #new<<<<<<<<<<<<<
                my $bitlist_str = $self->{intVal}->as_bin();
                $bitlist_str =~ s/^0b//;
                croak "\nThe value specified for size must be at least as large as for the " .
                      "smallest bitvector possible for the intVal integer: $!" 
                      if $self->{size} < length $bitlist_str;
                @bitarray = split //, $bitlist_str;
                my $n = $self->{size} - @bitarray;
                my $extended_bitlist_str = '0' x $n . $bitlist_str;
                @bitarray = split //, $extended_bitlist_str;
            } else {
                my $bitlist_str = sprintf "%b", $self->{intVal};
                if (defined $self->{size}) {
                    croak "\nThe value specified for size must be at least as large as for the " .
                          "smallest bitvector possible for the intVal integer: $!" 
                          if $self->{size} < length $bitlist_str;
                    my $n = $self->{size} - length $bitlist_str;
                    my $extended_bitlist_str = '0' x $n . $bitlist_str;
                    @bitarray = split //, $extended_bitlist_str;
                } else {
                    @bitarray = split //, $bitlist_str;
                }
            }
            $self->{bitlist} = \@bitarray;
            $self->{size} = scalar @{$self->{bitlist}};
        }
    } elsif (defined $self->{size}) {
        die "When using the `size' option in the constructor call, you CANNOT use `filename', " .
            "`bitlist', 'bitstring', `hexstring', or `textstring' options: $!" 
            if $self->{filename} or $self->{intVal} or $self->{bitlist} 
               or $self->{bitstring} or $self->{hexstring} or $self->{textstring};
        my $bitstring = "0" x $self->{size};   
        my @bitlist_from_bitstring  = split '', $bitstring;
        $self->{bitlist} = \@bitlist_from_bitstring;
    } elsif ($self->{bitlist}) {
        die "When using the `bitlist' option in the constructor call, you cannot use any " .

lib/Algorithm/BitVector.pm  view on Meta::CPAN

    if ( $bv1->{size} < $bv2->{size} ) {
        $bv3 = $bv1->_resize_pad_from_left($bv2->{size} - $bv1->{size});
        $bv4 = $bv2;
    } elsif ( $bv1->{size} > $bv2->{size} ) {
        $bv3 = $bv1;
        $bv4 = $bv2->_resize_pad_from_left($bv1->{size} - $bv2->{size});
    } else {
        $bv3 = $bv1;
        $bv4 = $bv2;
    }
    my $result_bv = Algorithm::BitVector->new( size => $bv3->{size} );
    foreach my $i (0..@{$result_bv->{_vector}}-1) {
        # The binary bitwise `&' operator may assume 32-bit wide fields:
        $result_bv->{_vector}->[$i] = ($bv3->{_vector}->[$i] & $bv4->{_vector}->[$i] ) & 0x0000FFFF;
    }
    return $result_bv;
}

##  Take a bitwise 'XOR' of the bitvector on which the method is invoked with
##  the argument bitvector.  Return the result as a new bitvector.  If the two
##  bitvectors are not of the same size, pad the shorter one with zeros from the
##  left.
sub _xor {
    my ($bv1, $bv2) = @_;    
    croak "Abort: The xor operator invoked with either undefined " .
        "or wrong types of operands: $!"
        unless UNIVERSAL::isa( $bv1, 'Algorithm::BitVector') and
        UNIVERSAL::isa( $bv2, 'Algorithm::BitVector');
    my ($bv3, $bv4);
    if ( $bv1->{size} < $bv2->{size} ) {
        $bv3 = $bv1->_resize_pad_from_left($bv2->{size} - $bv1->{size});
        $bv4 = $bv2;
    } elsif ( $bv1->{size} > $bv2->{size} ) {
        $bv3 = $bv1;
        $bv4 = $bv2->_resize_pad_from_left($bv1->{size} - $bv2->{size});
    } else {
        $bv3 = $bv1;
        $bv4 = $bv2;
    }
    my $result_bv = Algorithm::BitVector->new( size => $bv3->{size} );
    foreach my $i (0..@{$result_bv->{_vector}}-1) {
        # The binary bitwise `^' operator may assume 32-bit wide fields:
        $result_bv->{_vector}->[$i] = ($bv3->{_vector}->[$i] ^ $bv4->{_vector}->[$i] ) & 0x0000FFFF;
    }
    return $result_bv;
}

# For the overloading of the iterator '<>' operator:
sub _iter {
    my $self = shift;
    my $pos = 0;
    $self->{_iterator} = BitVecIterator->new($self, $pos) unless $self->{_iter_called};
    &{$self->{_iterator}->next()};
}

{
    # This inner class needed for implementing iterator overloading:
    package BitVecIterator;
    sub new {
        my $self = [ $_[1], $_[2] ];
        bless $self, $_[0];
        $_[1]->{_iter_called} = 1;
        return $self;
    }
    sub next {
        my $self = shift;
        my $bitvec = $self->[0];
        # The anonymous subroutine that follows is a closure over the variables
        # incorporated in it:
        return sub { 
            if ($self->[1] >= $bitvec->{size}) {
                delete $bitvec->{_iter_called};
                return;
            }
            my $bit = $bitvec->get_bit($self->[1]); 
            $self->[1] =  $self->[1] + 1;
            return $bit;
        } 
    }
}

# for the overloading of the numification operator:
sub _int {
    my $self = shift;
    return $self->int_value();
}

##  Divides an even-sized bitvector into two and returns the two halves as a
##  list of two bitvectors.
sub divide_into_two {
    my $self = shift;
    die "Abort: The divide_into_two() method invoked on an object that is " .
        "not of type Algorithm::BitVector"
        unless UNIVERSAL::isa( $self, 'Algorithm::BitVector');
    die "The bitvector to be divided must have even number of bits: $!"
        if $self->{size} % 2;
    my @outlist1 = ();
    foreach my $i (0..$self->{size} / 2 - 1) {
        push @outlist1, $self->get_bit($i);
    }
    my @outlist2 = ();
    foreach my $i ( ($self->{size} / 2) .. ($self->{size} - 1) ) {
        push @outlist2, $self->get_bit($i);
    }
    return Algorithm::BitVector->new( bitlist => \@outlist1 ), 
           Algorithm::BitVector->new( bitlist => \@outlist2 );
}

##  Permute a bitvector according to the indices shown in the second argument list.
##  Return the permuted bitvector as a new bitvector.
sub permute {
    my $self = shift;
    die "Abort: The permute() method invoked on an object that is " .
        "not of type Algorithm::BitVector"
        unless UNIVERSAL::isa( $self, 'Algorithm::BitVector');
    my $permute_list = shift;
    die "Bad permutation index in your permutation list" 
        if max(@$permute_list) > $self->{size} - 1;
    my @outlist = ();
    foreach my $index (@$permute_list) { 
        push @outlist, $self->get_bit($index);



( run in 0.975 second using v1.01-cache-2.11-cpan-6aa56a78535 )