/// <summary>Multiplies this matrix (the one on the left) by another matrix (the one on the right).</summary> public Matrix Times(Matrix right) { if (GetColumns() != right.GetRows()) { throw new ArgumentException("Columns on left (" + GetColumns() + ") " + "is different than rows on right (" + right.GetRows() + ")"); } var result = new Matrix(GetRows(), right.GetColumns()); for (int r = 0; r < GetRows(); r++) { for (int c = 0; c < right.GetColumns(); c++) { byte value = 0; for (int i = 0; i < GetColumns(); i++) { value ^= Galois.Multiply(Get(r, i), right.Get(i, c)); } result.Set(r, c, value); } } return(result); }
/// <summary> /// Create a Vandermonde matrix, which is guaranteed to have the property that any subset of rows that forms a /// square matrix is invertible. /// </summary> /// <param name="rows">Number of rows in the result.</param> /// <param name="cols">Number of columns in the result.</param> /// <returns>A Matrix.</returns> static Matrix Vandermonde(int rows, int cols) { var result = new Matrix(rows, cols); for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { result.Set(r, c, Galois.Exp((byte)r, c)); } } return(result); }
/// <summary>Does the work of matrix inversion. Assumes that this is an r by 2r matrix.</summary> 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] == 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. if (data[r][r] == 0) { throw new ArgumentException("Matrix is singular"); } // Scale to 1. if (data[r][r] != 1) { byte scale = Galois.Divide(1, data[r][r]); for (int c = 0; c < columns; c++) { data[r][c] = Galois.Multiply(data[r][c], scale); } } // Make everything below the 1 be a 0 by subtracting // a multiple of it. (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] ^= Galois.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] != 0) { byte scale = data[rowAbove][d]; for (int c = 0; c < columns; c++) { data[rowAbove][c] ^= Galois.Multiply(scale, data[d][c]); } } } } }