Binary matrix multiplication

Question:

I got a matrix A, with the following bytes as rows:

11111110  (0xfe)
11111000  (0xf8)
10000100  (0x84)
10010010  (0x92)

My program reads a byte from stdin with the function sys.stdin.read(1). Suppose I receive the byte x 10101010 (0xaa). Is there a way using numpy to perform the multiplication:

>>> A.dot(x)
0x06 (00000110)

As A is a 4×8 matrix, compossed by 4 bytes as rows, and x is an 8 bit array, I was expecting to receive the (nibble 0110) byte 0000 0110 as a result of the multiplication A * x, treating bits as elements of the matrix.

If the elements of the matrix were treated as binary bytes, the result would be:

>>> A = np.array([[1,1,1,1,1,1,1,0],[1,1,1,1,1,0,0,0],[1,0,0,0,0,1,0,0],[1,0,0,1,0,0,1,0]])
>>> x = np.array([1,0,1,0,1,0,1,0])
>>> A.dot(x)%2
array([0, 1, 1, 0])
Asked By: samba

||

Answers:

1. Not using dot

You do not need to fully expand your matrix to do bitwise “multiplication” on it. You want to treat A as a 4×8 matrix of bits and x as an 8-element vector of bits. A row multiplication yields 1 for the bits that are on in both A and x and 0 if either bit is 0. This is equivalent to applying bitwise and (&):

>>> [hex(n) for n in (A & x)]
['0xaa', '0xa8', '0x80', '0x82']

10101010
10101000
10000000
10000000

Here is a post on counting the bits in a byte. bin(n).count("1") is probably the easiest one to use, so

>>> [bin(n).count("1") % 2 for n in (A & x)]
[0, 1, 1, 0]

If you want just a number, you can do something like

>>> int(''.join(str(bin(n).count("1") % 2) for n in (A & x)), 2)
6

2. Using dot

To use dot, you can easily expand A and x into their numpy equivalents:

>>> list(list(int(n) for n in list(bin(r)[2:])) for r in A)
[['1', '1', '1', '1', '1', '1', '1', '0'],
 ['1', '1', '1', '1', '1', '0', '0', '0'],
 ['1', '0', '0', '0', '0', '1', '0', '0'],
 ['1', '0', '0', '1', '0', '0', '1', '0']]
>>> list(int(n) for n in bin(x)[2:])
[1, 0, 1, 0, 1, 0, 1, 0]

You can apply dot to the result:

>>> np.dot(list(list(int(n) for n in list(bin(r)[2:])) for r in A),
           list(int(n) for n in bin(x)[2:])) % 2
array([0, 1, 1, 0])
Answered By: Mad Physicist
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.