public void MultiplicationInGaliosFieldShouldWorkCorrect(byte firstOperand, byte secondOperand, uint irreduciblePolynomial, byte expectedResult) { //arrange var gfUnderTest = new GaloisField(irreduciblePolynomial); //act var actualResult = gfUnderTest.Multiply(firstOperand, secondOperand); //assert Assert.Equal(expectedResult, actualResult); }
/// <summary> /// Multiplies this matrix (the one on the left) by another matrix (the one on the right). /// </summary> public Matrix Multiply(Matrix right) { Throw.If(this.Columns != right.Rows, $"Columns on left ({this.Columns}) is different than rows on right ({right.Rows})"); Matrix result = new Matrix(this.Rows, right.Columns); for (int r = 0; r < this.Rows; r++) { for (int c = 0; c < right.Columns; c++) { byte value = 0; for (int i = 0; i < this.Columns; i++) { value ^= GaloisField.Multiply(Get(r, i), right.Get(i, c)); } result.Set(r, c, value); } } return(result); }
/// <summary> /// Does the work of matrix inversion. Assumes that this is an r by 2r matrix. /// </summary> private void GaussianElimination() { // Clear out the part below the main diagonal and scale the main diagonal to be 1. for (int r = 0; r < Rows; r++) { // If the element on the diagonal is 0, find a row below // that has a non-zero and swap them. if (_data[r, r] == (byte)0) { for (int rowBelow = r + 1; rowBelow < Rows; rowBelow++) { if (_data[rowBelow, r] != 0) { SwapRows(r, rowBelow); break; } } } // If we couldn't find one, the matrix is singular. Throw.If(_data[r, r] == 0, "Matrix is singular"); // Scale to 1. if (_data[r, r] != 1) { byte scale = GaloisField.Divide(1, _data[r, r]); for (int c = 0; c < Columns; c++) { _data[r, c] = GaloisField.Multiply(_data[r, c], scale); } } // Make everything below the 1 be a 0 by subtracting a multiple of it. // Note: subtraction and addition are both exclusive or in the Galois field. for (int rowBelow = r + 1; rowBelow < Rows; rowBelow++) { if (_data[rowBelow, r] != 0) { byte scale = _data[rowBelow, r]; for (int c = 0; c < Columns; c++) { _data[rowBelow, c] ^= GaloisField.Multiply(scale, _data[r, c]); } } } } // Now clear the part above the main diagonal. for (int d = 0; d < Rows; d++) { for (int rowAbove = 0; rowAbove < d; rowAbove++) { if (_data[rowAbove, d] != (byte)0) { byte scale = _data[rowAbove, d]; for (int c = 0; c < Columns; c++) { _data[rowAbove, c] ^= GaloisField.Multiply(scale, _data[d, c]); } } } } }