My current implementation is as follows, taken from this question and modified to use an exclusive or instead of addition as per comments here. The assumption is made (and, for the goal of this implementation, acceptable) that all input matrices will be 4x4.
/**
* Produces the product of two matrices, treating the first parameter as the "left" matrix.
*/
public static int[][] multiplyMatrices(int[][] a, int[][] b)
{
int[][] resultMatrix = new int[4][4];
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
for(int k = 0; k < 4; k++)
{
resultMatrix[i][j] = resultMatrix[i][j] ^ multiplyPolynomials(a[i][k], b[k][j]);
}
}
}
return resultMatrix;
}
The multiplyPolynomials
function is as described here.
/**
* Multiplies two polynomials (mod 2) represented as integers.
* The first is converted into a binary string, which is then used
* to select a number of appropriate bit shifts of the
* second, which are then added together.
*/
public static int multiplyPolynomials(int n, int m)
{
int result = 0x00000000;
String ns = toBitString(n);
for (int i = 0; i < ns.length(); i++)
{
int bitIndex = (ns.length() - i) -1;
if (ns.charAt(bitIndex) == '1')
{
int temp = m;
temp = temp << i;
result = result ^ temp;
}
}
return result;
}
After running multiplyMatrices
, resultMatrix
is passed as a parameter of reduceMatrix
, defined below, with the second parameter being given as 0x011b. (toBitString
is simply a shortcut for Integer.toBinaryString
.)
/*
* Reduces all elements of the matrix modulo a given polynomial.
* Treats the values as bit-string representations of polynomials mod 2.
* Works by XORing various left-shifts of the modulo value with the value being reduced.
* NOTE: This comment describes both reduceMatrix() and moduloReduce().
*/
public static int[][] reduceMatrix(int[][] m, int p)
{
int[][] reducedM = new int[4][4];
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
reducedM[i][j] = moduloReduce(m[i][j], p);
}
}
return reducedM;
}
public static int moduloReduce(int f, int p)
{
String fs = toBitString(f);
String ps = toBitString(p);
int temp = f;
int q = 0;
while (toBitString(temp).length() >= ps.length())
{
int j = toBitString(temp).length()-1;
int k = ps.length()-1;
q = p << (j-k);
temp = temp ^ q;
}
return temp;
}
This was tested using the following two matrices as input, with the values given being explicitly in hexadecimal:
02 03 01 01
01 02 03 01
01 01 02 03
03 01 01 02
----------
10 26 03 15
23 41 33 04
51 32 14 43
12 12 12 12
With those inputs, the output matrix (in hexadecimal, reduced mod 0x011b) is:
10 26 03 15
23 41 33 04
51 32 14 43
12 12 12 12
However, completing the reduction by hand produces a different result:
06 af 55 7c
b7 e0 4b ca
a7 35 2e a1
66 3d 06 5c
So clearly the program as written is not working correctly. However, the following second input matrix (using the same first matrix) returns the correct result:
30 ca 96 24
32 92 09 23
3f ca 43 63
7d 5a f8 96
The expected (and received) result for the above input is as follows:
74 b2 97 d8
68 ea b9 51
fb 39 0a 60
a7 a9 00 1b
Clearly, the output of multiplyMatrices
is not the expected result in all cases. The matrix multiplication algorithm used appears to have worked for the poster of the linked question, and I have previously verified that multiplyPolynomials
works as expected. What is the most likely cause of the inaccurate output from multiplyMatrices
, and why do some inputs produce the correct output anyway?