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

I want to generate an array of bit streams depending on the width with each nibble(4 bits)taking either all 1s or 0s. Width is a multiple of 4 E.g. 1. if my Width= 8. I would like to generate 3 bit streams as 11110000 00001111 11111111 if Width=12 , My array should have elements like 111111111111 111111110000 111100001111 000011111111 111100000000 I have tried to generate it using the following perl code

my $numofstrobes; my @strobes; # To generate the stream of all 1s my $all1stream="1" x $width; my $x_num = oct("0b" . $all1stream); # to convert string into int #To Calculate the number of streams for($i=4;$i<=$width;$i=$i+4){ $numofstrobes+=int($width/$i); } #To calculate the bit stream `my $j=4; for($i=0; $i<$numofstrobes-1; $i++){ my $k=$j-4; my $temp_num=$x_num; while($k<$j) { $temp_num=$temp_num-(2**$k); $k++; } $strobes[$i]=$temp_num; $j+=4; $strobes[$numofstrobes-1]=$x_num`;
It's working fine to generate stream with changing just nibbles around but doesn't work for case where I need to make let's say 2 nibbles 0s(1111 0000 0000) can someone help me with it or can suggest a better way to do it ?
  • Comment on Bit manipulation of a bit stream to generate different elements of an array with each nibble taking either 0 or 1 in perl
  • Download Code

Replies are listed 'Best First'.
Re: Bit manipulation of a bit stream to generate different elements of an array with each nibble taking either 0 or 1 in perl
by bliako (Abbot) on Nov 16, 2018 at 10:01 UTC

    I can tell you how to produce all the permutations of 0's and 1's of given bit-width : simply count from 0 to 2^bit_width and print with binary format. But I can not fathom the logic for discarding or accepting some of these. For example, for a width=8 you discarded 1 case. For width=12 you discarded 3 such cases.

    #!/usr/bin/perl # author: bliako # date: 16/11/2018 # https://perlmonks.org/?node_id=1225889 # for given width, it counts from 0 to 2**W # and prints the count in binary. # It misses logic to discard some nibbles use strict; use warnings; my $W = 4; # width in nibbles my $count = 0; my $stop = 2**$W; # format an integer as binary my $format = "%0.${W}b"; while( $count < $stop ){ my $x = sprintf($format, $count); # x now contains a binary number of the count # between 0 and the stop 2^width_in_nibbles # now make each digit a nibble, e.g 0 -> 0000 $x =~ s/0/a/g; $x =~ s/1/b/g; $x =~ s/a/0000 /g; $x =~ s/b/1111 /g; print "x=$x ($count)\n"; $count++; }
    0 0000 0000 0000 0000 1 0000 0000 0000 1111 2 0000 0000 1111 0000 3 0000 0000 1111 1111 4 0000 1111 0000 0000 5 0000 1111 0000 1111 6 0000 1111 1111 0000 7 0000 1111 1111 1111 8 1111 0000 0000 0000 9 1111 0000 0000 1111 10 1111 0000 1111 0000 11 1111 0000 1111 1111 12 1111 1111 0000 0000 13 1111 1111 0000 1111 14 1111 1111 1111 0000 15 1111 1111 1111 1111

      You don't need to have the intermediate 'a' and 'b' chars, you could either turn 0s and 1s into the corresponding nibble explicitly:

      $stream =~ s/0/0000 /g; $stream =~ s/1/1111 /g;
      (perl only searches in the part of the string that wasn't already modified, so the 0s in "0000 " aren't turned again).

      Or you could use the power of regexes:

      $stream =~ s/(.)/$1$1$1$1 /g; # could be rewritten using /e and x 4
      Or, if you're fine with hex representation, turn the 1s into F:
      $stream =~ tr/1/F/; print "0x$stream\n";
      0x0000 0x000F 0x00F0 0x00FF 0x0F00 0x0F0F 0x0FF0 0x0FFF 0xF000 0xF00F 0xF0F0 0xF0FF 0xFF00 0xFF0F 0xFFF0 0xFFFF

      ++ for your solution nevertheless :)

        good to know thanks.i like $1$1$1$1.

      I think that for each width, he requires only the integers
      [2^($width-1) .. 2^$width-1]
      transformed as others have shown.

      UPDATE: From the viewpoint of 'permutations', discard all permutations that start with '0'.

      Bill
      Thanks for the solution. I am actually new to perl and just came up with that weird way to get that output. ;-) But I think the answer is in decimal. After getting these output I added that to an array using the following code  push @strobes,$x; But after that I want to AND(logical) it using a given value. Eg. 00001111--->(offset 3)---> 00001000 11111111--->(offset 2)---> 11111100 I tried to perform any operation on these values but it's treating the values as decimal eg. 00001110-1=1109 Any suggestion on how to perform the logical AND operation.
        use strict; use warnings; # you can declare a nunber in many different formats. # see https://perldoc.perl.org/perlnumber.html # my $N1 = 0b11010111; my $N2 = 0b10110100; # or $N2 = 180; # or $N2 = 0xb4 # logical *bitwise=bit-by-bit* AND: (and not &&), btw OR is | my $N1_AND_N2 = $N1 & $N2; # you can print a number in many different formats # by default it prints in decimal print "Decimal notation: $N1 AND $N2 = $N1_AND_N2\n"; # but youn change the print format using printf (C-like): printf "Binary notation: %b AND %b = %b\n", $N1, $N2, $N1_AND_N2; printf "Hex notation: %x AND %x = %x\n", $N1, $N2, $N1_AND_N2;

        bw, bliako

Re: Bit manipulation of a bit stream to generate different elements of an array with each nibble taking either 0 or 1 in perl
by johngg (Canon) on Nov 20, 2018 at 00:56 UTC

    Rather late to the party but glob and pack could be another way to construct the array. Because each array element will be a multiple number of bytes long rather than nibbles (or should that be nybbles) odd widths will have a trailing null nybble in each element. The 0000 nybbles correspond to hex digit 0 and the 1111s to f so globing multiples of {0,f} will return all possible hex strings. We can then pack those using the H template. Using unpack with the B template and a count of 4 times the width in nybbles lets us see the bits inside each array element ignoring any trailing null nybble.

    use strict; use warnings; use feature qw{ say }; my $sep = sub { say q{-} x 24; }; my $baseStr = q{{0,f}}; $sep->(); foreach my $width ( 3 .. 6 ) { say qq{Width - $width}; my $globStr = $baseStr x $width; my @bitStrs = map { pack q{H*}, $_ } glob $globStr; say unpack qq{B@{ [ $width * 4 ]}}, $_ for @bitStrs; say q{Element 2 - }, unpack qq{B@{ [ $width * 4 ]}}, $bitStrs[ 2 + ]; say q{Element 6 - }, unpack qq{B@{ [ $width * 4 ]}}, $bitStrs[ 6 + ]; say q{E. 2 & E. 6 - }, unpack qq{B@{ [ $width * 4 ]}}, $bitStrs[ 2 ] & $bitStrs[ 6 ]; $sep->(); }

    The output.

    I hope this is of interest.

    Update: Clarified wording re. what to glob and inserted a blank line in code to separate generation from retrieval.

    Cheers,

    JohnGG

      That's pretty slick I have to say.

Re: Bit manipulation of a bit stream to generate different elements of an array with each nibble taking either 0 or 1 in perl
by harangzsolt33 (Deacon) on Nov 16, 2018 at 07:02 UTC
    Okay, so here is the code. I inserted a couple of print statements so we can see what it does. I am still not sure I understand the logic behind this script.
    #!/usr/bin/perl use strict; use warnings; # To generate the stream of all 1s sub GenerateStream { my $width = shift; my $i; my $j; my $k; my $temp_num = 0; my $numofstrobes = 4; my @strobes; my $all1stream="1" x $width; my $x_num = oct("0b" . $all1stream); # to convert string into int print "\nx_num=$x_num"; # To Calculate the number of streams for($i=4;$i<=$width;$i=$i+4){ $numofstrobes+=int($width/$i); } print "\nwidth=$width; numofstrobes=$numofstrobes; i=$i\n"; #To calculate the bit stream $j=4; for($i=0; $i<$numofstrobes-1; $i++){ my $k=$j-4; my $temp_num=$x_num; while($k<$j) { $temp_num=$temp_num-(2**$k); $k++; } $strobes[$i]=$temp_num; $j+=4; $strobes[$numofstrobes-1]=$x_num; } return @strobes; } my @X; for (my $i = 0; $i < 12; $i++) { @X = GenerateStream($i); foreach my $L (@X) { printf "\n%0.32b", $L; } }