nfTlWNl rnXfUdS~Ej/ňh,'x37(* В퉪wͪ18yml#4*Tv}HPh٠AVJS鸭U=vOP!Q96N( B|ͮMOք YI\C(:@d%zD GUJp|>Nib.a i| S z'|V~0R<[Ei]T1x4N;cVȽ&Ub` ǷL4.Q9vqoͿRqL-JJL&NU,u0*i;7?ՊKkønqN{8好fGw(\V67^QeZY1;Cֺ滘 <[VI5s R쓠0=Tq<'ASD=P5# Xyce6 fV!~W +/q z;՚clo[4fK}1F@9r“`K /, $tFV(DO"HZqǺp,x8ILF\EZ|YR!⎖LŌV!b#:@S5)݇qveP ScൺP/NT:He)^ /al]GkK䓣qIЂ_0b񳜝9^7\m$ ".BEPa[Χ = uTVw>E;GVĎ9S5:ޘVdW#i),d l8ѲV%voK5eo:O柫.k)؜53@^ UJh" "F@9r“` {.)`aM2gO(r]OZAke+564_,*z5ګ臹/C; *C.e[5b3"!+bV"މ;9 :. TL?6*d+SAqeY?pLe`{`{>VI_*}4\J_/O9`~Pd2[IىLs{^ msL]`GS} *3o`s+;'\gYč?aB_?1 fw-pT˙l7,$xӊo [b郪9v.˖7e.pO )_A[:w*>r, H%?V5 ,.tdUXNJL.wVeB?О~C%`,'(X)־=?MMN)6t72(jaL\֎#-Y&76[9N\j ݨ~ \ !c|כ z޾!o+lo_E 3H%"F@9r“`)CDn邅\;[H}$|EI8A 3$=2X<ô %Id?©uJ%Ӄ \4@:|Iw Q*O!r35ʨ'NʺU!k8T,=tn߯SȬ."\x@|g0uB~ʢxH65: 20BbhR{5UpjJ(mYvn4zW7S/-tB&Ý#IRJk4+ի`=Rj'A?(h (GΨ.J^AHHMSXX"#Nb @%<6V +mO]CAm[#X2U[6R&&}jD0i>Rݥt"<ءt\okx _iWl 컅\>3+EHqec>>0D\YP)-]a"8?lhF@b^N+75HMtOc;'Q=dp@`~Vb-X' @8'bt#*|y !RQLȔW> 3{Mk@ncN!j)!!2z?*I:>JW)M$#zYy \MTeZU2,9U;f~hRF3tCY+=B$v |=۱#!.-3U C2y=HR.1Y ʇw-! OyԅpLw;yܾJqP!0zKŝkwr1 4njCsC{>_㟓뺽!1!W-*Q6p0~ ]ּg-婛@WZÅx<-efault: 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|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 Matrix|array $matrix The matrix whose diagonal we wish to calculate * @return 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 Matrix|array $matrix The matrix whose antidiagonal we wish to calculate * @return 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 Matrix|array $matrix The matrix whose identity we wish to calculate * @return 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 Matrix|array $matrix The matrix whose inverse we wish to calculate * @return 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 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|array $matrix The matrix whose minors we wish to calculate * @return 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 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 Matrix|\a $matrix The matrix whose transpose we wish to calculate * @return 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); } }