in reply to Reading individual bits

If I'm reading this correctly, the bitstring your passing in is an "ascii-ized binary" string? If so, then the conversion of your strings from real binary to ascii-ized binary is the source of one performance hit. You should not need to do that.

Have you looked at vec? It only deals with powers-of-two numbers of bits, but it it may fit your needs. If not it is easily adapted to do so.

You can almost certainly get away with not padding your numbers with trailing zeros before conversion, pack and unpack are pretty clever about such things.

I'd have had a go at providing an alternative subroutine, but it's structure--the way it maintains values in the callers scope through references--plus the confusion over the terms 'binary' and 'bitstring' would mean making (possibly wrong) guesses about this subroutines use.

Perhaps you could post a short program that sets up a piece of test data, and then calls this subroutine to extract a couple of values from it?


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

Replies are listed 'Best First'.
Re^2: Reading individual bits
by iKnowNothing (Scribe) on Jul 29, 2004 at 23:26 UTC
    Sure thing, here's a program that shows basically how I use the function.
    @ItemList = (); #this would be filled with some data already, and pass +ed in as a reference. $ItemListRef = \@ItemList; $LCSStatWd1 = 524288; #this would normally come from the file $LCSStatWd1Bits = unpack("B32",pack("N",$LCSStatWd1)); #creating the b +it string print "$LCSStatWd1Bits\n"; #Discretes $Offset = 0; $LidarPwrState = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $LidarPwrStateToggle = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRe +f); $LCSMode = ReadBits($LCSStatWd1Bits,\$Offset,6,$ItemListRef); $LidarCondition = ReadBits($LCSStatWd1Bits,\$Offset,3,$ItemListRef); $NewCentAvail = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $ObjOutOfScnWin = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $ReAcqFailed = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $LaserState = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $GrCommEnable = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $LidarMode = ReadBits($LCSStatWd1Bits,\$Offset,2,$ItemListRef); $LCSSubMode = ReadBits($LCSStatWd1Bits,\$Offset,3,$ItemListRef); $GNCpredit = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $FOVedgemAz = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $FOVedgepAz = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $FOVedgemEl = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $FOVedgepEl = ReadBits($LCSStatWd1Bits,\$Offset,1,$ItemListRef); $Spare2 = ReadBits($LCSStatWd1Bits,\$Offset,6,$ItemListRef); sub ReadBits { my $BitStringIn = @_[0]; my $OffsetRef = @_[1]; my $Length = @_[2]; my $ItemListRef = @_[3]; my $BitStringOut = 0; $BitStringOut = substr($BitStringIn,$$OffsetRef,$Length); $$OffsetRef += $Length; $NumZeros = 32-$Length; $Zeros = unpack("B$NumZeros",pack("N",0)); $BitStringOut = $Zeros.$BitStringOut; $NumOut = unpack("N",pack("B32",$BitStringOut)); @$ItemListRef = (@$ItemListRef,$NumOut, "\t"); print "\n$NumOut"; return($NumOut); }
    I did look at vec, however it didn't look like it would work for me since I sometimes read 3 or 6 bits. I'll try taking out the padding, I thought that each number would need to be the same length to do the conversion right.

      This performs bit mask operations upon 32-bit values thereby saving the need to ascii-ize the binary.

      #! perl -slw use strict; sub getBits { my( $N32, $offset, $bits ) = @_; my $mask = 1 << $bits; $mask--; $mask <<= $offset; return ( $N32 & $mask ) >> $offset; } ## Encode some test data. my $data = unpack 'N', pack 'b*', #0123456789 123456789 123456789 1 '11101111101111111011111111101111'; # 7 31 127 511 15 print $data; ## 4160617975 print getBits( $data, 0, 3 ); ## Should be 7 print getBits( $data, 4, 5 ); ## should be 31 print getBits( $data, 10, 7 ); ## Should be 127 print getBits( $data, 18, 9 ); ## Should be 511 print getBits( $data, 28, 4 ); ## Should be 15 __END__ P:\test>test 4160617975 7 31 127 511 15

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon

      Whilst I'm looking, this bit of code is very strange--and slow.

      @$ItemListRef = (@$ItemListRef,$NumOut, "\t");

      You

      1. pass in a reference to an array,
      2. dereference that array to produce a list,
      3. tack the latest value and a tab onto the end of the list
      4. and then assign that back to the original array.

      This action is the same as doing:

      push @$ItemListRef, $NumOut, "\t";

      Accept that it uses gob-loads (tech. term) of memory in building lots of intermediate lists in the process. No wonder your subroutine is slow.

      Also, why are you interspersing your values with tabs?

      If the intention is to print them as tab-delimited list to a file or the screen. Just build the array without the inspersed tabs and then use join to add teh tabs when you print.

      print join "\t", @ItemList;

      Not only will you save half the memory of your list, by not allocating it you'll save a bit more time.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
        you can also use perl's $, variable to set the "output field seperator" to put tabs in between a elements passed to print in a list.

        i.e.

        rather than:
        print join "\t", @ItemList;

        you could do:
        local $, = "\t"; print @ItemList;

        doing a quick profile of these showed only a 3-4% increase in speed so code readability might outweigh performance in this case