See Release Notes
Long Term Support Release
<?php namespace Matrix; class Functions { /**> * Validates an array of matrix, converting an array to a matrix if required. * Calculate the adjoint of the matrix > * * > * @param Matrix|array $matrix Matrix or an array to treat as a matrix. * @param Matrix $matrix The matrix whose adjoint we wish to calculate > * @return Matrix The new matrix * @return Matrix > * @throws Exception If argument isn't a valid matrix or array. * > */ * @throws Exception > private static function validateMatrix($matrix) */ > { private static function getAdjoint(Matrix $matrix) > if (is_array($matrix)) { { > $matrix = new Matrix($matrix); return self::transpose( > } self::getCofactors($matrix) > if (!$matrix instanceof Matrix) { ); > throw new Exception('Must be Matrix or array'); } > } > /** > return $matrix; * Return the adjoint of this matrix > } * The adjugate, classical adjoint, or adjunct of a square matrix is the transpose of its cofactor matrix. > * The adjugate has sometimes been called the "adjoint", but today the "adjoint" of a matrix normally refers > /*** to its corresponding adjoint operator, which is its conjugate transpose. *< * @param Matrix $matrix The matrix whose adjoint we wish to calculate> * @param Matrix|array $matrix The matrix whose adjoint we wish to calculate* @return Matrix * @throws Exception **/< public static function adjoint(Matrix $matrix)> public static function adjoint($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Adjoint can only be calculated for a square matrix'); } return self::getAdjoint($matrix); } /** * Calculate the cofactors of the matrix * * @param Matrix $matrix The matrix whose cofactors we wish to calculate * @return Matrix * * @throws Exception */ private static function getCofactors(Matrix $matrix) { $cofactors = self::getMinors($matrix); $dimensions = $matrix->rows; $cof = 1; for ($i = 0; $i < $dimensions; ++$i) { $cofs = $cof; for ($j = 0; $j < $dimensions; ++$j) { $cofactors[$i][$j] *= $cofs; $cofs = -$cofs; } $cof = -$cof; } return new Matrix($cofactors); } /** * Return the cofactors of this matrix *< * @param Matrix $matrix The matrix whose cofactors we wish to calculate> * @param Matrix|array $matrix The matrix whose cofactors we wish to calculate* @return Matrix * * @throws Exception */< public static function cofactors(Matrix $matrix)> public static function cofactors($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Cofactors can only be calculated for a square matrix'); } return self::getCofactors($matrix); } /** * @param Matrix $matrix * @param int $row * @param int $column * @return float * @throws Exception */ private static function getDeterminantSegment(Matrix $matrix, $row, $column) { $tmpMatrix = $matrix->toArray(); unset($tmpMatrix[$row]); array_walk( $tmpMatrix, function (&$row) use ($column) { unset($row[$column]); } ); return self::getDeterminant(new Matrix($tmpMatrix)); } /** * Calculate the determinant of the matrix * * @param Matrix $matrix The matrix whose determinant we wish to calculate * @return float * * @throws Exception */ private static function getDeterminant(Matrix $matrix) { $dimensions = $matrix->rows; $determinant = 0; switch ($dimensions) { case 1: $determinant = $matrix->getValue(1, 1); break; case 2: $determinant = $matrix->getValue(1, 1) * $matrix->getValue(2, 2) - $matrix->getValue(1, 2) * $matrix->getValue(2, 1); break; default: for ($i = 1; $i <= $dimensions; ++$i) { $det = $matrix->getValue(1, $i) * self::getDeterminantSegment($matrix, 0, $i - 1); if (($i % 2) == 0) { $determinant -= $det; } else { $determinant += $det; } } break; } return $determinant; } /** * Return the determinant of this matrix *< * @param Matrix $matrix The matrix whose determinant we wish to calculate> * @param Matrix|array $matrix The matrix whose determinant we wish to calculate* @return float * @throws Exception **/< public static function determinant(Matrix $matrix)> public static function determinant($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Determinant can only be calculated for a square matrix'); } return self::getDeterminant($matrix); } /** * Return the diagonal of this matrix *< * @param Matrix $matrix The matrix whose diagonal we wish to calculate> * @param Matrix|array $matrix The matrix whose diagonal we wish to calculate* @return Matrix * @throws Exception **/< public static function diagonal(Matrix $matrix)> public static function diagonal($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Diagonal can only be extracted from a square matrix'); } $dimensions = $matrix->rows; $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions) ->toArray(); for ($i = 0; $i < $dimensions; ++$i) { $grid[$i][$i] = $matrix->getValue($i + 1, $i + 1); } return new Matrix($grid); } /** * Return the antidiagonal of this matrix *< * @param Matrix $matrix The matrix whose antidiagonal we wish to calculate> * @param Matrix|array $matrix The matrix whose antidiagonal we wish to calculate* @return Matrix * @throws Exception **/< public static function antidiagonal(Matrix $matrix)> public static function antidiagonal($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Anti-Diagonal can only be extracted from a square matrix'); } $dimensions = $matrix->rows; $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions) ->toArray(); for ($i = 0; $i < $dimensions; ++$i) { $grid[$i][$dimensions - $i - 1] = $matrix->getValue($i + 1, $dimensions - $i); } return new Matrix($grid); } /** * Return the identity matrix * The identity matrix, or sometimes ambiguously called a unit matrix, of size n is the n × n square matrix * with ones on the main diagonal and zeros elsewhere *< * @param Matrix $matrix The matrix whose identity we wish to calculate> * @param Matrix|array $matrix The matrix whose identity we wish to calculate* @return Matrix * @throws Exception **/< public static function identity(Matrix $matrix)> public static function identity($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Identity can only be created for a square matrix'); } $dimensions = $matrix->rows; return Builder::createIdentityMatrix($dimensions); } /** * Return the inverse of this matrix *< * @param Matrix $matrix The matrix whose inverse we wish to calculate> * @param Matrix|array $matrix The matrix whose inverse we wish to calculate* @return Matrix * @throws Exception **/< public static function inverse(Matrix $matrix)> public static function inverse($matrix, string $type = 'inverse'){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >< throw new Exception('Inverse can only be calculated for a square matrix');> throw new Exception(ucfirst($type) . ' can only be calculated for a square matrix');} $determinant = self::getDeterminant($matrix); if ($determinant == 0.0) {< throw new Exception('Inverse can only be calculated for a matrix with a non-zero determinant');> throw new Div0Exception(ucfirst($type) . ' can only be calculated for a matrix with a non-zero determinant');} if ($matrix->rows == 1) { return new Matrix([[1 / $matrix->getValue(1, 1)]]); } return self::getAdjoint($matrix) ->multiply(1 / $determinant); } /** * Calculate the minors of the matrix * * @param Matrix $matrix The matrix whose minors we wish to calculate * @return array[] * * @throws Exception */ protected static function getMinors(Matrix $matrix) { $minors = $matrix->toArray(); $dimensions = $matrix->rows; if ($dimensions == 1) { return $minors; } for ($i = 0; $i < $dimensions; ++$i) { for ($j = 0; $j < $dimensions; ++$j) { $minors[$i][$j] = self::getDeterminantSegment($matrix, $i, $j); } } return $minors; } /** * Return the minors of the matrix * The minor of a matrix A is the determinant of some smaller square matrix, cut down from A by removing one or * more of its rows or columns. * Minors obtained by removing just one row and one column from square matrices (first minors) are required for * calculating matrix cofactors, which in turn are useful for computing both the determinant and inverse of * square matrices. *< * @param Matrix $matrix The matrix whose minors we wish to calculate> * @param Matrix|array $matrix The matrix whose minors we wish to calculate* @return Matrix * @throws Exception **/< public static function minors(Matrix $matrix)> public static function minors($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Minors can only be calculated for a square matrix'); } return new Matrix(self::getMinors($matrix)); } /** * Return the trace of this matrix * The trace is defined as the sum of the elements on the main diagonal (the diagonal from the upper left to the lower right) * of the matrix *< * @param Matrix $matrix The matrix whose trace we wish to calculate> * @param Matrix|array $matrix The matrix whose trace we wish to calculate* @return float * @throws Exception **/< public static function trace(Matrix $matrix)> public static function trace($matrix){> $matrix = self::validateMatrix($matrix); if (!$matrix->isSquare()) { >throw new Exception('Trace can only be extracted from a square matrix'); } $dimensions = $matrix->rows; $result = 0; for ($i = 1; $i <= $dimensions; ++$i) { $result += $matrix->getValue($i, $i); } return $result; } /** * Return the transpose of this matrix *< * @param Matrix $matrix The matrix whose transpose we wish to calculate> * @param Matrix|\a $matrix The matrix whose transpose we wish to calculate* @return Matrix **/< public static function transpose(Matrix $matrix)> public static function transpose($matrix){> $matrix = self::validateMatrix($matrix); $array = array_values(array_merge([null], $matrix->toArray())); >$grid = call_user_func_array( 'array_map', $array ); return new Matrix($grid); } }