AlkantarClanX12

Your IP : 18.116.14.12


Current Path : /home/thanudqk/www/wp-content/plugins/tablepress/libraries/vendor/Matrix/
Upload File :
Current File : /home/thanudqk/www/wp-content/plugins/tablepress/libraries/vendor/Matrix/Functions.php

<?php

namespace TablePress\Matrix;

class Functions
{
	/**
	 * Validates an array of matrix, converting an array to a matrix if required.
	 *
	 * @param TablePress\Matrix|array $matrix TablePress\Matrix or an array to treat as a matrix.
	 * @return TablePress\Matrix The new matrix
	 * @throws Exception If argument isn't a valid matrix or array.
	 */
	private static function validateMatrix($matrix)
	{
		if (is_array($matrix)) {
			$matrix = new Matrix($matrix);
		}
		if (!$matrix instanceof Matrix) {
			throw new Exception('Must be TablePress\Matrix or array');
		}

		return $matrix;
	}

	/**
	 * Calculate the adjoint of the matrix
	 *
	 * @param TablePress\Matrix $matrix The matrix whose adjoint we wish to calculate
	 * @return TablePress\Matrix
	 *
	 * @throws Exception
	 */
	private static function getAdjoint(TablePress\Matrix $matrix)
	{
		return self::transpose(
			self::getCofactors($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 TablePress\Matrix|array $matrix The matrix whose adjoint we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	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 TablePress\Matrix $matrix The matrix whose cofactors we wish to calculate
	 * @return TablePress\Matrix
	 *
	 * @throws Exception
	 */
	private static function getCofactors(TablePress\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 TablePress\Matrix|array $matrix The matrix whose cofactors we wish to calculate
	 * @return TablePress\Matrix
	 *
	 * @throws Exception
	 */
	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 TablePress\Matrix $matrix
	 * @param int $row
	 * @param int $column
	 * @return float
	 * @throws Exception
	 */
	private static function getDeterminantSegment(TablePress\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 TablePress\Matrix $matrix The matrix whose determinant we wish to calculate
	 * @return float
	 *
	 * @throws Exception
	 */
	private static function getDeterminant(TablePress\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 TablePress\Matrix|array $matrix The matrix whose determinant we wish to calculate
	 * @return float
	 * @throws Exception
	 **/
	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 TablePress\Matrix|array $matrix The matrix whose diagonal we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	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 TablePress\Matrix|array $matrix The matrix whose antidiagonal we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	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 TablePress\Matrix|array $matrix The matrix whose identity we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	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 TablePress\Matrix|array $matrix The matrix whose inverse we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	public static function inverse($matrix, string $type = 'inverse')
	{
		$matrix = self::validateMatrix($matrix);

		if (!$matrix->isSquare()) {
			throw new Exception(ucfirst($type) . ' can only be calculated for a square matrix');
		}

		$determinant = self::getDeterminant($matrix);
		if ($determinant == 0.0) {
			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 TablePress\Matrix $matrix The matrix whose minors we wish to calculate
	 * @return array[]
	 *
	 * @throws Exception
	 */
	protected static function getMinors(TablePress\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 TablePress\Matrix|array $matrix The matrix whose minors we wish to calculate
	 * @return TablePress\Matrix
	 * @throws Exception
	 **/
	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 TablePress\Matrix|array $matrix The matrix whose trace we wish to calculate
	 * @return float
	 * @throws Exception
	 **/
	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 TablePress\Matrix|\a $matrix The matrix whose transpose we wish to calculate
	 * @return TablePress\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);
	}
}