GNU Info

Info Node: (gawk.info)Bitwise Functions

(gawk.info)Bitwise Functions


Next: I18N Functions Prev: Time Functions Up: Built-in
Enter node , (file) or (file)node

Using `gawk''s Bit Manipulation Functions
-----------------------------------------

     I can explain it for you, but I can't understand it for you.
     Anonymous

   Many languages provide the ability to perform "bitwise" operations
on two integer numbers.  In other words, the operation is performed on
each successive pair of bits in the operands.  Three common operations
are bitwise AND, OR, and XOR.  The operations are described by the
following table:

                     Bit Operator
               |  AND  |   OR  |  XOR
               |---+---+---+---+---+---
     Operands  | 0 | 1 | 0 | 1 | 0 | 1
     ----------+---+---+---+---+---+---
         0     | 0   0 | 0   1 | 0   1
         1     | 0   1 | 1   1 | 1   0

   As you can see, the result of an AND operation is 1 only when _both_
bits are 1.  The result of an OR operation is 1 if _either_ bit is 1.
The result of an XOR operation is 1 if either bit is 1, but not both.
The next operation is the "complement"; the complement of 1 is 0 and
the complement of 0 is 1. Thus, this operation "flips" all the bits of
a given value.

   Finally, two other common operations are to shift the bits left or
right.  For example, if you have a bit string `10111001' and you shift
it right by three bits, you end up with `00010111'.(1) If you start over
again with `10111001' and shift it left by three bits, you end up with
`11001000'.  `gawk' provides built-in functions that implement the
bitwise operations just described. They are:

`and(V1, V2)'          Return the bitwise AND of the values provided by V1
                       and V2.
`or(V1, V2)'           Return the bitwise OR of the values provided by V1 and
                       V2.
`xor(V1, V2)'          Return the bitwise XOR of the values provided by V1
                       and V2.
`compl(VAL)'           Return the bitwise complement of VAL.
`lshift(VAL, COUNT)'   Return the value of VAL, shifted left by COUNT bits.
`rshift(VAL, COUNT)'   Return the value of VAL, shifted right by COUNT bits.

   For all of these functions, first the double-precision
floating-point value is converted to a C `unsigned long', then the
bitwise operation is performed and then the result is converted back
into a C `double'. (If you don't understand this paragraph, don't worry
about it.)

   Here is a user-defined function (*note User-Defined Functions:
User-defined.)  that illustrates the use of these functions:

     # bits2str --- turn a byte into readable 1's and 0's
     
     function bits2str(bits,        data, mask)
     {
         if (bits == 0)
             return "0"
     
         mask = 1
         for (; bits != 0; bits = rshift(bits, 1))
             data = (and(bits, mask) ? "1" : "0") data
     
         while ((length(data) % 8) != 0)
             data = "0" data
     
         return data
     }
     
     BEGIN {
         printf "123 = %s\n", bits2str(123)
         printf "0123 = %s\n", bits2str(0123)
         printf "0x99 = %s\n", bits2str(0x99)
         comp = compl(0x99)
         printf "compl(0x99) = %#x = %s\n", comp, bits2str(comp)
         shift = lshift(0x99, 2)
         printf "lshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift)
         shift = rshift(0x99, 2)
         printf "rshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift)
     }

This program produces the following output when run:

     $ gawk -f testbits.awk
     -| 123 = 01111011
     -| 0123 = 01010011
     -| 0x99 = 10011001
     -| compl(0x99) = 0xffffff66 = 11111111111111111111111101100110
     -| lshift(0x99, 2) = 0x264 = 0000001001100100
     -| rshift(0x99, 2) = 0x26 = 00100110

   The `bits2str' function turns a binary number into a string.  The
number `1' represents a binary value where the rightmost bit is set to
1.  Using this mask, the function repeatedly checks the rightmost bit.
AND-ing the mask with the value indicates whether the rightmost bit is
1 or not. If so, a `"1"' is concatenated onto the front of the string.
Otherwise, a `"0"' is added.  The value is then shifted right by one
bit and the loop continues until there are no more 1 bits.

   If the initial value is zero it returns a simple `"0"'.  Otherwise,
at the end, it pads the value with zeros to represent multiples of
eight-bit quantities. This is typical in modern computers.

   The main code in the `BEGIN' rule shows the difference between the
decimal and octal values for the same numbers (Note: Octal and
Hexadecimal Numbers.), and then demonstrates the
results of the `compl', `lshift', and `rshift' functions.

   ---------- Footnotes ----------

   (1) This example shows that 0's come in on the left side. For
`gawk', this is always true, but in some languages, it's possible to
have the left side fill with 1's. Caveat emptor.


automatically generated by info2www version 1.2.2.9