LanX has asked for the wisdom of the Perl Monks concerning the following question:

Hi

I'm not often working with vec , pack and unpack but whats the way to display a 16 bit-vector with MSB to the left?

DB<138> undef $m0; vec($m0,$_,1)=1 for 0,2,8,9,10 DB<139> p unpack('b16', $m0) # ok LSB left 1010000011100000 DB<140> p unpack('B16', $m0) # MSB, but inside LS + bytes chunks 0000010100000111 DB<142> $x+= 2**$_ for 0,2,8,9,10 DB<144> printf "%016b",$x # what I expected 0000011100000101 DB<145>

update

well it's documented

B A bit string (descending bit order inside each byte).

but there must be a better way than

DB<184> p reverse unpack ('B8B8',$m0) 0000011100000101 DB<185>

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Replies are listed 'Best First'.
Re: Displaying bit-vectors with Most Significant Bits to the left?
by ikegami (Patriarch) on Jan 05, 2020 at 08:05 UTC

    One could say that vec produces a packed little-endian integer. The bytes are ordered from most significant to least significant. In other words,

    my $m0; vec($m0, $_, 1) = 1 for 0,2,8,9,10;

    is equivalent to

    my $m0l; vec($m0l, $_, 1) = 1 for 0,2; my $m0h; vec($m0h, $_-8, 1) = 1 for 8,9,10; my $m0 = $m0l . $m0h;

    Option 1: Reverse the order of the bytes then convert the bytes to binary one by one.

    unpack "B16", scalar reverse $mo

    Option 2: Unpack the bytes into a number, and print the binary representation of that number

    sprintf "%016b", unpack "v", $m0
Re: Displaying bit-vectors with Most Significant Bits to the left?
by johngg (Canon) on Jan 05, 2020 at 12:18 UTC

    Creating the vector in one 16-bit operation rather than several 1-bit operations simplifies the unpack process.

    johngg@shiraz:~/perl/Monks$ perl -Mstrict -Mwarnings -E ' my @bitPosns = ( 0, 2, 8, 9, 10 ); my $val; $val += 2 ** $_ for @bitPosns; my $vec; vec( $vec, 0, 16 ) = $val; say unpack q{B16}, $vec;' 0000011100000101

    Six of one, a half dozen of the other I suppose.

    Cheers,

    JohnGG

      The OP didn't give any indication that $m0 was different than expected. Changing the value of $m0 doesn't seem appropriate. But if it is, there are two improvements you can make.


      When doing bit arithmetic, most people prefer to use actual bit arithmetic instead of powers. Not only is it more intuitive to use operations that match one's mental model, your approach fails if a bit is already set. Replace

      $val += 2 ** $_

      with

      $val |= 1 << $_

      As evidenced by these posts, vec is quite weird, so it's surely best to avoid it if it doesn't offer a benefit.

      my $vec; vec( $vec, 0, 16 ) = $val;

      can be replaced with

      my $vec = pack 'n', $val;

        > vec is quite weird, so it's surely best to avoid it if it doesn't offer a benefit.

        I think it's trying to hide the machine representation of a number.

        I "grew up" on motorola, that's why I'm still confused.

        But vec's approach might provide reproducible results on different architectures.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: Displaying bit-vectors with Most Significant Bits to the left?
by shmem (Chancellor) on Jan 05, 2020 at 14:31 UTC
    but there must be a better way than
    DB<184> p reverse unpack ('B8B8',$m0) 0000011100000101 DB<185>

    Sure, since unpack 'B8B8' yields a list with 2 bytes. I'd say

    DB<185> p reverse unpack 'b16',$m0 0000011100000101 DB<186>
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      Using reverse on a single value in list context is a no-op.

      You posted untested code in a fake demo.

      So clever!

      DB<315> undef $m1; vec($m1,$_,1)=1 for 0,2,8,9,10 DB<316> x unpack 'b16',$m1 0 1010000011100000 DB<317> p reverse unpack 'b16',$m1 1010000011100000 DB<318> p scalar reverse unpack 'b16',$m1 0000011100000101 DB<319>

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

        You posted untested code in a fake demo.

        So clever!

        Thanks for calling me a fool. So nice!

        p scalar reverse unpack 'b16',$m1

        Yeah, the scalar was missing, which you spotted and corrected.

        So what?

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'