From 0f76d0646dcd580f8b94ecddc105e2375a1382b4 Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Fri, 11 Feb 2022 15:04:02 +0000 Subject: [PATCH] Created BigIntegerMatrix --- .../mattrixwv/matrix/BigIntegerMatrix.java | 783 ++++++++++++++++++ 1 file changed, 783 insertions(+) create mode 100644 src/main/java/com/mattrixwv/matrix/BigIntegerMatrix.java diff --git a/src/main/java/com/mattrixwv/matrix/BigIntegerMatrix.java b/src/main/java/com/mattrixwv/matrix/BigIntegerMatrix.java new file mode 100644 index 0000000..dd463e1 --- /dev/null +++ b/src/main/java/com/mattrixwv/matrix/BigIntegerMatrix.java @@ -0,0 +1,783 @@ +//Matrix/src/main/java/com/mattrixwv/BigIntegerMatrix.java +//Mattrixwv +// Created: 02-10-22 +//Modified: 02-10-22 +package com.mattrixwv.matrix; + + +import java.math.BigInteger; +import java.util.StringJoiner; + +import com.mattrixwv.matrix.exceptions.InvalidCoordinatesException; +import com.mattrixwv.matrix.exceptions.InvalidGeometryException; +import com.mattrixwv.matrix.exceptions.InvalidRowSizeException; +import com.mattrixwv.matrix.exceptions.InvalidScalarException; + + +public class BigIntegerMatrix{ + protected BigInteger[][] grid; + + //Helper functions + protected void setGrid(BigInteger[][] grid){ + if(grid.length == 0){ + this.grid = new BigInteger[0][0]; + } + else if(grid[0].length == 0){ + this.grid = new BigInteger[grid.length][0]; + } + else{ + //Make sure all rows are the same length + int length = grid[0].length; + for(int cnt = 1;cnt < grid.length;++cnt){ + if(grid[cnt].length != length){ + throw new InvalidRowSizeException("All rows in a matrix must be the same size"); + } + } + + //Copy every element over to a new grid + BigInteger[][] newGrid = new BigInteger[grid.length][grid[0].length]; + for(int rowCnt = 0;rowCnt < grid.length;++rowCnt){ + for(int colCnt = 0;colCnt < grid[0].length;++colCnt){ + newGrid[rowCnt][colCnt] = grid[rowCnt][colCnt]; + } + } + + //Save the new grid + this.grid = newGrid; + } + } + protected BigInteger[][] copyGrid(){ + //Allocate memory for the new grid + BigInteger[][] newGrid = new BigInteger[grid.length][grid[0].length]; + + //Copy every element from the current grid to the new one + for(int row = 0;row < grid.length;++row){ + for(int col = 0;col < grid[0].length;++col){ + newGrid[row][col] = grid[row][col]; + } + } + + //Return the new grid + return newGrid; + } + protected boolean isSquare(){ + if(getNumRows() == 0){ + return false; + } + else{ + return getNumRows() == getNumCols(); + } + } + //Returns a matrix with the supplied row and column removed + protected BigIntegerMatrix laplaceExpansionHelper(int row, int col){ + //Make sure the matrix is square + if(!isSquare()){ + throw new InvalidGeometryException("A matrix must be square for you to perform Laplace Expansion"); + } + //Make sure the matrix is large enough to have this operation performed + if((getNumRows() <= 1) || (getNumCols() <= 1)){ + throw new InvalidGeometryException("A matrix must be at least 2x2 for you to perform Laplace Expansion: " + getNumRows() + "x" + getNumCols()); + } + //Make sure the row is valid + if((row < 0) || (row >= getNumRows())){ + throw new InvalidCoordinatesException("An invalid row number was supplied: " + row + ". The matrix contains " + getNumRows() + " rows"); + } + //Make sure the col is valid + if((col < 0) || (col >= getNumCols())){ + throw new InvalidCoordinatesException("An invalid column number was supplied: " + col + ". The matrix contains " + getNumCols() + " columns"); + } + + + //Create a new matrix that is one row and column smaller than the existing row + BigInteger[][] newGrid = new BigInteger[getNumRows() - 1][getNumCols() - 1]; + //Traverse the matrix and set the values in the new matrix, skipping elements in the given row and col + for(int workingRow = 0, newRow = 0;workingRow < getNumRows();++workingRow){ + //Skip the row we are expanding + if(workingRow == row){ + continue; + } + for(int workingCol = 0, newCol = 0;workingCol < getNumCols();++workingCol){ + //Skip the column we are expanding + if(workingCol == col){ + continue; + } + newGrid[newRow][newCol] = grid[workingRow][workingCol]; + ++newCol; + } + ++newRow; + } + + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + + //Constructors + public BigIntegerMatrix(){ + grid = new BigInteger[0][0]; + } + public BigIntegerMatrix(BigInteger[][] grid){ + setGrid(grid); + } + public BigIntegerMatrix(BigIntegerMatrix matrix){ + setGrid(matrix.grid); + } + public BigIntegerMatrix(int rows, int cols, BigInteger fill){ + if(rows <= 0){ + throw new InvalidGeometryException("A filled matrix must have at least 1 row"); + } + else if(cols <= 0){ + throw new InvalidGeometryException("A filled matrix must have at least 1 column"); + } + else{ + grid = new BigInteger[rows][cols]; + for(int row = 0;row < rows;++row){ + for(int col = 0;col < cols;++col){ + grid[row][col] = fill; + } + } + } + } + + //Gets + public BigInteger get(int row, int col){ + //Make sure the row and column are valid + if(row >= grid.length){ + throw new InvalidCoordinatesException("Row cannot be greater than the number of rows"); + } + else if(col >= grid[0].length){ + throw new InvalidCoordinatesException("Column cannot be greater than the number of columns"); + } + + //Return the location in the grid + return grid[row][col]; + } + public BigIntegerMatrix getRow(int row){ + //Make sure the row number is valid + if((row < 0) || (row >= grid.length)){ + throw new InvalidCoordinatesException("The row number " + row + " is not valid"); + } + + //Generate a copy of the row + BigInteger[][] newRow = new BigInteger[1][grid[row].length]; + for(int col = 0;col < grid[row].length;++col){ + newRow[0][col] = grid[row][col]; + } + + //Return the new matrix + return new BigIntegerMatrix(newRow); + } + public int getNumRows(){ + if(grid == null){ + return 0; + } + else{ + return grid.length; + } + } + public BigIntegerMatrix getCol(int col){ + //Make sure the column number is valid + if((col < 0) || (grid.length == 0) || (col > grid[0].length)){ + throw new InvalidCoordinatesException("The column number " + col + " is not valid"); + } + + //Generate a copy of the col + BigInteger[][] newColumn = new BigInteger[grid.length][1]; + for(int row = 0;row < grid.length;++row){ + newColumn[row][0] = grid[row][col]; + } + + //Return the new matrix + return new BigIntegerMatrix(newColumn); + } + public int getNumCols(){ + if(grid.length > 0){ + return grid[0].length; + } + else{ + return 0; + } + } + //Sets + public void set(int row, int col, BigInteger value){ + //Make sure the row number is valid + if((row < 0) || (row >= grid.length)){ + throw new InvalidCoordinatesException("Invalid row number " + row); + } + //Make sure the column number is valid + if((col < 0) || (col >= getNumCols())){ + throw new InvalidCoordinatesException("Invalid column number " + col); + } + + //Save the element + grid[row][col] = value; + } + public void setRow(int row, BigInteger[] elements){ + //Make sure the row number is valid + if((row < 0) || (row >= grid.length)){ + throw new InvalidCoordinatesException("Invalid row number " + row); + } + //Make sure the number of elements is valid + if(elements.length != getNumCols()){ + throw new InvalidGeometryException("Invalid number of elements " + elements.length + " must be " + getNumCols()); + } + + //Save the elements + for(int col = 0;col < elements.length;++col){ + grid[row][col] = elements[col]; + } + } + public void setRow(int row, BigIntegerMatrix matrix){ + //Make sure the matrix has a single row + if(matrix.getNumRows() != 1){ + throw new InvalidGeometryException("Setting a row by Matrix requires the matrix contain a single row"); + } + + //Set the row + setRow(row, matrix.grid[0]); + } + public void setCol(int col, BigInteger[] elements){ + //Make sure the column number is valid + if((col < 0) || (col >= getNumCols())){ + throw new InvalidCoordinatesException("Invalid column number " + col); + } + //Make sure the number of elements is valid + if(elements.length != grid.length){ + throw new InvalidCoordinatesException("Invalid number of elements " + elements.length + " must be " + grid.length); + } + + //Save the elements + for(int row = 0;row < elements.length;++row){ + grid[row][col] = elements[row]; + } + } + public void setCol(int col, BigIntegerMatrix matrix){ + //Make sure the matrix has a single column + if(matrix.getNumCols() != 1){ + throw new InvalidGeometryException("Setting a column by Matrix requires the matrix contain a single column"); + } + + //Set the column + setCol(col, matrix.getCol(0)); + } + //Adds + public void addRow(BigInteger[] elements){ + //Make sure the number of columns is valid + if((grid.length == 0) || (getNumCols() == elements.length)){ + BigInteger[][] newGrid = new BigInteger[grid.length + 1][elements.length]; + //Copy all existing data into the new grid + for(int row = 0;row < grid.length;++row){ + newGrid[row] = grid[row]; + } + grid = newGrid; + } + else{ + throw new InvalidGeometryException("Invalid number of elements " + elements.length + " must be " + getNumCols()); + } + + //Add all elements to the grid + for(int col = 0;col < elements.length;++col){ + grid[grid.length - 1][col] = elements[col]; + } + } + public void addRow(BigIntegerMatrix matrix){ + //Make sure the matrix has a single row + if(matrix.getNumRows() != 1){ + throw new InvalidGeometryException("Adding a row by Matrix requires the matrix contain a single row"); + } + + //Add the row + addRow(matrix.grid[0]); + } + public void addCol(BigInteger[] elements){ + //Make sure the number of rows is valid + if(grid.length == 0){ + grid = new BigInteger[1][elements.length]; + } + else if(grid.length == elements.length){ + //Copy all existing data into the new grid + for(int row = 0;row < grid.length;++row){ + BigInteger[] workingRow = new BigInteger[grid[row].length + 1]; + for(int workingCol = 0;workingCol < grid[row].length;++workingCol){ + workingRow[workingCol] = grid[row][workingCol]; + } + grid[row] = workingRow; + } + } + else{ + throw new InvalidGeometryException("Invalid number of elements " + elements.length + " must be " + getNumCols()); + } + + //Add all elements to the grid + for(int row = 0;row < elements.length;++row){ + grid[row][grid[row].length - 1] = elements[row]; + } + } + public void addCol(BigIntegerMatrix matrix){ + //Make sure the matrix has a single column + if(matrix.getNumCols() != 1){ + throw new InvalidGeometryException("Adding a column by Matrix requires the matrix contain a single column"); + } + + //Add the column + addCol(matrix.getCol(0)); + } + public BigIntegerMatrix appendRight(BigIntegerMatrix rightSide){ + //Make sure the matrices have the same number of rows + if(getNumRows() != rightSide.getNumRows()){ + throw new InvalidGeometryException("Invalid number of rows. " + rightSide.getNumRows() + " must be " + getNumRows()); + } + + //Traverse both matrices and set their values in the new matrix + BigInteger[][] newGrid = new BigInteger[getNumRows()][getNumCols() + rightSide.getNumCols()]; + for(int row = 0;row < getNumRows();++row){ + //Set all elements from the current grid's row + for(int col = 0;col < getNumCols();++col){ + newGrid[row][col] = grid[row][col]; + } + //Set all elements from the right side grid's row + for(int col = 0;col < rightSide.getNumCols();++col){ + newGrid[row][getNumCols() + col] = rightSide.grid[row][col]; + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix appendBottom(BigIntegerMatrix rightSide){ + //Make sure the matrices have the same number of columns + if(getNumCols() != rightSide.getNumCols()){ + throw new InvalidGeometryException("Invalid number of columns. " + rightSide.getNumCols() + " must be " + getNumCols()); + } + + //Traverse both matrices and set their values in the new matrix + BigInteger[][] newGrid = new BigInteger[getNumRows() + rightSide.getNumRows()][getNumCols()]; + for(int col = 0;col < getNumCols();++col){ + //Set all elements from the current grid's column + for(int row = 0;row < getNumRows();++row){ + newGrid[row][col] = grid[row][col]; + } + //Set all elements from the right side grid's column + for(int row = 0;row < rightSide.getNumRows();++row){ + newGrid[getNumRows() + row][col] = rightSide.grid[row][col]; + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + + //Simple operations + public static BigIntegerMatrix generateIdentity(int size){ + //Make sure the size is valid + if(size > 0){ + //Create a grid with the correct size + BigInteger[][] newGrid = new BigInteger[size][size]; + + //Go through every element and make sure it is set correctly + for(int row = 0;row < size;++row){ + for(int col = 0;col < size;++col){ + if(col == row){ + newGrid[row][col] = BigInteger.ONE; + } + else{ + newGrid[row][col] = BigInteger.ZERO; + } + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + else{ + throw new InvalidGeometryException("An identity matrix must have a size > 0"); + } + } + public BigIntegerMatrix add(BigIntegerMatrix rightSide){ + //Make sure the matrices have compatable geometry + if((getNumRows() != rightSide.getNumRows()) || (getNumCols() != rightSide.getNumCols())){ + throw new InvalidGeometryException("Both matrices must have the same number of rows and columns: " + getNumRows() + "x" + getNumCols() + " + " + rightSide.getNumRows() + "x" + rightSide.getNumCols()); + } + + //Create a new grid with the same elements as the current grid + BigInteger[][] newGrid = copyGrid(); + + //Add each element in the righ tmatrix to the corresponding element in the left matrix + for(int row = 0;row < newGrid.length;++row){ + for(int col = 0;col < newGrid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].add(rightSide.grid[row][col]); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix add(BigInteger scalar){ + //Create a new grid with the same elements as the current grid + BigInteger[][] newGrid = copyGrid(); + + //Add the scalar to each element in the grid + for(int row = 0;row < newGrid.length;++row){ + for(int col = 0;col < newGrid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].add(scalar); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix subtract(BigIntegerMatrix rightSide){ + //Make sure the matrices have compatable geometry + if((getNumRows() != rightSide.getNumRows()) || (getNumCols() != rightSide.getNumCols())){ + throw new InvalidGeometryException("Both matrices must have the same number of rows and columsn: " + getNumRows() + "x" + getNumCols() + " + " + rightSide.getNumRows() + "x" + rightSide.getNumCols()); + } + + //Create a new grid with the same elements as the current gird + BigInteger[][] newGrid = copyGrid(); + + //Subtract each element in the righ tmatrix from the corresponding element in the left matrix + for(int row = 0;row < newGrid.length;++row){ + for(int col = 0;col < newGrid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].subtract(grid[row][col]); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix subtract(BigInteger scalar){ + //Create a new grid with the same elements as the current grid + BigInteger[][] newGrid = copyGrid(); + + //Subtract the scalar from each element in the grid + for(int row = 0;row < newGrid.length;++row){ + for(int col = 0;col < newGrid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].subtract(scalar); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix multiply(BigIntegerMatrix rightSide){ + //Make sure the matrices have compatable geometry + if(getNumCols() != rightSide.getNumRows()){ + throw new InvalidGeometryException("The left matrix must have the same number of columns as the right matrix has rows: " + getNumRows() + "x" + getNumCols() + " + " + rightSide.getNumRows() + "x" + rightSide.getNumCols()); + } + + //Create a new grid with the same elements as the current grid + BigInteger[][] newGrid = new BigInteger[getNumRows()][rightSide.getNumCols()]; + + //Multiply each row in the left matrix with each column int he right matrix to come up with the current element + for(int leftRow = 0;leftRow < grid.length;++leftRow){ + for(int rightCol = 0;rightCol < rightSide.getNumCols();++rightCol){ + //Get a sum of the product of each column in the current row (left) and each row in the current column (right) + BigInteger elementProductSum = BigInteger.ZERO; + for(int incrementCounter = 0;incrementCounter < grid.length;++incrementCounter){ + elementProductSum = elementProductSum.add(grid[leftRow][incrementCounter].multiply(rightSide.grid[incrementCounter][rightCol])); + } + newGrid[leftRow][rightCol] = elementProductSum; + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix multiply(BigInteger scalar){ + //Create a new grid with the same elements as the current grid + BigInteger[][] newGrid = copyGrid(); + + //Multiply every element in the grid by the scalar + for(int row = 0;row < grid.length;++row){ + for(int col = 0;col < grid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].multiply(scalar); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix pow(int power){ + //Make sure the matrix is square so it can be multiplied + if(!isSquare()){ + throw new InvalidGeometryException("The matrix must be square to raise it to a power"); + } + //Make sure the power is positive + if(power < 0){ + throw new InvalidScalarException("The power must be >= 0"); + } + else if(power == 0){ + return new BigIntegerMatrix(getNumRows(), getNumCols(), BigInteger.ONE); + } + + //Create a new matrix for the product + BigIntegerMatrix newMatrix = clone(); + //Multiply the current grid power times + for(int currentPower = 1;currentPower < power;++currentPower){ + newMatrix = newMatrix.multiply(this); + } + + //Return the new grid + return newMatrix; + } + public BigInteger dotProduct(BigIntegerMatrix rightSide){ + //Make sure the matrices have compatable geometry + if(getNumCols() != rightSide.getNumRows()){ + throw new InvalidGeometryException("The left matrix must have the same number of columns as the right matrix has rows: " + getNumRows() + "x" + getNumCols() + " + " + rightSide.getNumRows() + "x" + rightSide.getNumCols()); + } + + //Multiply each row in the left matrix with each column in the right matrix to come up with the current element + //?Would be simpler, but slower, to get the product matrix to come up with the current element + BigInteger sum = BigInteger.ZERO; + for(int leftRow = 0;leftRow < grid.length;++leftRow){ + for(int rightCol = 0;rightCol < rightSide.getNumCols();++rightCol){ + for(int incrementCounter = 0;incrementCounter < grid.length;++incrementCounter){ + sum = sum.add(grid[leftRow][incrementCounter].multiply(rightSide.grid[incrementCounter][rightCol])); + } + } + } + + //Return the sum + return sum; + } + public BigIntegerMatrix hadamardProduct(BigIntegerMatrix rightSide){ + //Make sure the matrices have compatable geometry + if((getNumRows() != rightSide.getNumRows()) || (getNumCols() != rightSide.getNumCols())){ + throw new InvalidGeometryException("Both matrices must have the same number of rows and columns: " + getNumRows() + "x" + getNumCols() + " + " + rightSide.getNumRows() + "x" + rightSide.getNumCols()); + } + + //Create a new grid with the same element as the current grid + BigInteger[][] newGrid = copyGrid(); + + //Multiply each element in the right matrix to the corresponding element in the left matrix + for(int row = 0;row < newGrid.length;++row){ + for(int col = 0;col < newGrid[0].length;++col){ + newGrid[row][col] = newGrid[row][col].multiply(rightSide.grid[row][col]); + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + + //Complex operations + public BigIntegerMatrix transpose(){ + //Create a new grid + BigInteger[][] newGrid = new BigInteger[getNumCols()][getNumRows()]; + + //Traverse every element in the existing grid and add each column to the new grid as a row + for(int col = 0;col < getNumCols();++col){ + for(int row = 0;row < getNumRows();++row){ + newGrid[col][row] = grid[row][col]; + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigInteger det(){ + return determinant(); + } + public BigInteger determinant(){ + //Make sure the matrix is square + if(!isSquare()){ + throw new InvalidGeometryException("A matrix must be square for it to have a determinant"); + } + //?Don't have to worry about a matrix existing. isSquare takes care of 0x0 matrix + + //Determine the formula do use for the determinant + BigInteger det = BigInteger.ZERO; + switch(getNumRows()){ + //If the matrix is 1x1 return the number + case 1 : det = grid[0][0]; break; + //If the matrix is 2x2 use the formula + case 2 : { + det = (grid[0][0].multiply(grid[1][1])).subtract(grid[0][1].multiply(grid[1][0])); + } + break; + //If the matrix is 3x3 use the formula + case 3 : { + det = grid[0][0].multiply(grid[1][1]).multiply(grid[2][2]).add(grid[0][1].multiply(grid[1][2]).multiply(grid[2][0])).add(grid[0][2].multiply(grid[1][0]).multiply(grid[2][1])).subtract + (grid[2][0].multiply(grid[1][1]).multiply(grid[0][2])).subtract(grid[2][1].multiply(grid[1][2]).multiply(grid[0][0])).subtract(grid[2][2].multiply(grid[1][0]).multiply(grid[0][1])); + } + break; + //If the matrix is larger break it down and try again + default : { + //Find the row/column with the largest number of 0's + int zerosLocation = 0; + int maxNumZeros = 0; + boolean zerosRow = true; + //Check the rows + for(int row = 0;row < getNumRows();++row){ + int numZeros = 0; + for(int col = 0;col < getNumCols();++col){ + if(grid[row][col].equals(BigInteger.ZERO)){ + ++numZeros; + } + } + if(numZeros > maxNumZeros){ + maxNumZeros = numZeros; + zerosLocation = row; + zerosRow = true; + } + } + //Check the columns + for(int col = 0;col < getNumCols();++col){ + int numZeros = 0; + for(int row = 0;row < getNumRows();++row){ + if(grid[row][col].equals(BigInteger.ZERO)){ + ++numZeros; + } + } + if(numZeros > maxNumZeros){ + maxNumZeros = numZeros; + zerosLocation = col; + zerosRow = false; + } + } + + //If the largest number of zeros were found in a row + if(zerosRow){ + //Set a variable to make sure the appropriate + or - is applied to the scalar + BigInteger multiplier = BigInteger.ONE; + if((zerosLocation % 2) == 1){ + multiplier = BigInteger.ONE.negate(); + } + //Go through every column in the optimal row using the formula + for(int col = 0;col < getNumCols();++col){ + if(!grid[zerosLocation][col].equals(BigInteger.ZERO)){ + det = det.add(multiplier.multiply(grid[zerosLocation][col]).multiply(laplaceExpansionHelper(zerosLocation, col).determinant())); + } + multiplier = multiplier.negate(); + } + } + //If the largest number of zeros were found in a column + else{ + //Set a variable to make sure the appropriate + or - is applied to the scalar + BigInteger multiplier = BigInteger.ONE; + if((zerosLocation % 2) == 1){ + multiplier = BigInteger.ONE.negate(); + } + //Go through every row in the coptimal column using the formula + for(int row = 0;row < getNumRows();++row){ + if(!grid[row][zerosLocation].equals(BigInteger.ZERO)){ + det = det.add(multiplier.multiply(grid[row][zerosLocation]).multiply(laplaceExpansionHelper(row, zerosLocation).determinant())); + } + multiplier = multiplier.negate(); + } + } + } + } + + //Return the determinant + return det; + } + public BigIntegerMatrix cof(){ + return cofactor(); + } + public BigIntegerMatrix cofactor(){ + //Make sure the matrix is square + if(!isSquare()){ + throw new InvalidGeometryException("A matrix must be square to find the cofactor matrix"); + } + + //Create a new grid + BigInteger[][] newGrid = new BigInteger[getNumRows()][getNumCols()]; + //If the grid is 1x1 return the grid + if(getNumRows() == 1){ + newGrid[0][0] = BigInteger.ONE; + } + //Use the formula to find the cofactor matrix + else{ + for(int row = 0;row < getNumRows();++row){ + int multiplier = ((row % 2) == 0) ? 1 : -1; + for(int col = 0;col < getNumCols();++col){ + newGrid[row][col] = laplaceExpansionHelper(row, col).determinant().multiply(BigInteger.valueOf(multiplier)); + multiplier = -multiplier; + } + } + } + + //Return the new matrix + return new BigIntegerMatrix(newGrid); + } + public BigIntegerMatrix adj(){ + return adjoint(); + } + public BigIntegerMatrix adjoint(){ + return cofactor().transpose(); + } + public BigIntegerMatrix inverse(){ + //Make sure the matrix is square + if(!isSquare()){ + throw new InvalidGeometryException("A matrix must be square for it to have an inverse"); + } + + //Make sure the determinant is not 0 + BigInteger determinant = determinant(); + if(determinant.equals(BigInteger.ZERO)){ + throw new InvalidScalarException("The determinant cannot be 0"); + } + + //Return the new matrix + return adjoint().multiply(BigInteger.ONE.divide(determinant)); + } + + //Object funtions + @Override + public boolean equals(Object rightSide){ + if(rightSide.getClass().equals(this.getClass())){ + BigIntegerMatrix rightMatrix = (BigIntegerMatrix)rightSide; + + //Make sure they have the same number of elements + if(getNumRows() != rightMatrix.getNumRows()){ + return false; + } + else if(getNumCols() != rightMatrix.getNumCols()){ + return false; + } + + //Check every element + for(int row = 0;row < getNumRows();++row){ + for(int col = 0;col < getNumCols();++col){ + if(!grid[row][col].equals(rightMatrix.grid[row][col])){ + return false; + } + } + } + + //If false hasn't been returned yet then they are equal + return true; + } + else if(rightSide.getClass().equals(BigInteger[][].class)){ + BigInteger[][] rightMatrix = (BigInteger[][])rightSide; + + return equals(new BigIntegerMatrix(rightMatrix)); + } + else{ + return false; + } + } + @Override + public int hashCode(){ + return grid.hashCode(); + } + @Override + public String toString(){ + StringJoiner matrix = new StringJoiner("\n"); + for(int rowCnt = 0;rowCnt < getNumRows();++rowCnt){ + StringJoiner row = new StringJoiner(",", "[", "]"); + + for(int colCnt = 0;colCnt < getNumCols();++colCnt){ + row.add(grid[rowCnt][colCnt].toString()); + } + + matrix.add(row.toString()); + } + return matrix.toString(); + } + @Override + public BigIntegerMatrix clone(){ + return new BigIntegerMatrix(grid); + } +}