See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
1 <?php 2 3 namespace Matrix; 4 5 class Functions 6 { 7 /** 8 * Validates an array of matrix, converting an array to a matrix if required. 9 * 10 * @param Matrix|array $matrix Matrix or an array to treat as a matrix. 11 * @return Matrix The new matrix 12 * @throws Exception If argument isn't a valid matrix or array. 13 */ 14 private static function validateMatrix($matrix) 15 { 16 if (is_array($matrix)) { 17 $matrix = new Matrix($matrix); 18 } 19 if (!$matrix instanceof Matrix) { 20 throw new Exception('Must be Matrix or array'); 21 } 22 23 return $matrix; 24 } 25 26 /** 27 * Calculate the adjoint of the matrix 28 * 29 * @param Matrix $matrix The matrix whose adjoint we wish to calculate 30 * @return Matrix 31 * 32 * @throws Exception 33 */ 34 private static function getAdjoint(Matrix $matrix) 35 { 36 return self::transpose( 37 self::getCofactors($matrix) 38 ); 39 } 40 41 /** 42 * Return the adjoint of this matrix 43 * The adjugate, classical adjoint, or adjunct of a square matrix is the transpose of its cofactor matrix. 44 * The adjugate has sometimes been called the "adjoint", but today the "adjoint" of a matrix normally refers 45 * to its corresponding adjoint operator, which is its conjugate transpose. 46 * 47 * @param Matrix|array $matrix The matrix whose adjoint we wish to calculate 48 * @return Matrix 49 * @throws Exception 50 **/ 51 public static function adjoint($matrix) 52 { 53 $matrix = self::validateMatrix($matrix); 54 55 if (!$matrix->isSquare()) { 56 throw new Exception('Adjoint can only be calculated for a square matrix'); 57 } 58 59 return self::getAdjoint($matrix); 60 } 61 62 /** 63 * Calculate the cofactors of the matrix 64 * 65 * @param Matrix $matrix The matrix whose cofactors we wish to calculate 66 * @return Matrix 67 * 68 * @throws Exception 69 */ 70 private static function getCofactors(Matrix $matrix) 71 { 72 $cofactors = self::getMinors($matrix); 73 $dimensions = $matrix->rows; 74 75 $cof = 1; 76 for ($i = 0; $i < $dimensions; ++$i) { 77 $cofs = $cof; 78 for ($j = 0; $j < $dimensions; ++$j) { 79 $cofactors[$i][$j] *= $cofs; 80 $cofs = -$cofs; 81 } 82 $cof = -$cof; 83 } 84 85 return new Matrix($cofactors); 86 } 87 88 /** 89 * Return the cofactors of this matrix 90 * 91 * @param Matrix|array $matrix The matrix whose cofactors we wish to calculate 92 * @return Matrix 93 * 94 * @throws Exception 95 */ 96 public static function cofactors($matrix) 97 { 98 $matrix = self::validateMatrix($matrix); 99 100 if (!$matrix->isSquare()) { 101 throw new Exception('Cofactors can only be calculated for a square matrix'); 102 } 103 104 return self::getCofactors($matrix); 105 } 106 107 /** 108 * @param Matrix $matrix 109 * @param int $row 110 * @param int $column 111 * @return float 112 * @throws Exception 113 */ 114 private static function getDeterminantSegment(Matrix $matrix, $row, $column) 115 { 116 $tmpMatrix = $matrix->toArray(); 117 unset($tmpMatrix[$row]); 118 array_walk( 119 $tmpMatrix, 120 function (&$row) use ($column) { 121 unset($row[$column]); 122 } 123 ); 124 125 return self::getDeterminant(new Matrix($tmpMatrix)); 126 } 127 128 /** 129 * Calculate the determinant of the matrix 130 * 131 * @param Matrix $matrix The matrix whose determinant we wish to calculate 132 * @return float 133 * 134 * @throws Exception 135 */ 136 private static function getDeterminant(Matrix $matrix) 137 { 138 $dimensions = $matrix->rows; 139 $determinant = 0; 140 141 switch ($dimensions) { 142 case 1: 143 $determinant = $matrix->getValue(1, 1); 144 break; 145 case 2: 146 $determinant = $matrix->getValue(1, 1) * $matrix->getValue(2, 2) - 147 $matrix->getValue(1, 2) * $matrix->getValue(2, 1); 148 break; 149 default: 150 for ($i = 1; $i <= $dimensions; ++$i) { 151 $det = $matrix->getValue(1, $i) * self::getDeterminantSegment($matrix, 0, $i - 1); 152 if (($i % 2) == 0) { 153 $determinant -= $det; 154 } else { 155 $determinant += $det; 156 } 157 } 158 break; 159 } 160 161 return $determinant; 162 } 163 164 /** 165 * Return the determinant of this matrix 166 * 167 * @param Matrix|array $matrix The matrix whose determinant we wish to calculate 168 * @return float 169 * @throws Exception 170 **/ 171 public static function determinant($matrix) 172 { 173 $matrix = self::validateMatrix($matrix); 174 175 if (!$matrix->isSquare()) { 176 throw new Exception('Determinant can only be calculated for a square matrix'); 177 } 178 179 return self::getDeterminant($matrix); 180 } 181 182 /** 183 * Return the diagonal of this matrix 184 * 185 * @param Matrix|array $matrix The matrix whose diagonal we wish to calculate 186 * @return Matrix 187 * @throws Exception 188 **/ 189 public static function diagonal($matrix) 190 { 191 $matrix = self::validateMatrix($matrix); 192 193 if (!$matrix->isSquare()) { 194 throw new Exception('Diagonal can only be extracted from a square matrix'); 195 } 196 197 $dimensions = $matrix->rows; 198 $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions) 199 ->toArray(); 200 201 for ($i = 0; $i < $dimensions; ++$i) { 202 $grid[$i][$i] = $matrix->getValue($i + 1, $i + 1); 203 } 204 205 return new Matrix($grid); 206 } 207 208 /** 209 * Return the antidiagonal of this matrix 210 * 211 * @param Matrix|array $matrix The matrix whose antidiagonal we wish to calculate 212 * @return Matrix 213 * @throws Exception 214 **/ 215 public static function antidiagonal($matrix) 216 { 217 $matrix = self::validateMatrix($matrix); 218 219 if (!$matrix->isSquare()) { 220 throw new Exception('Anti-Diagonal can only be extracted from a square matrix'); 221 } 222 223 $dimensions = $matrix->rows; 224 $grid = Builder::createFilledMatrix(0, $dimensions, $dimensions) 225 ->toArray(); 226 227 for ($i = 0; $i < $dimensions; ++$i) { 228 $grid[$i][$dimensions - $i - 1] = $matrix->getValue($i + 1, $dimensions - $i); 229 } 230 231 return new Matrix($grid); 232 } 233 234 /** 235 * Return the identity matrix 236 * The identity matrix, or sometimes ambiguously called a unit matrix, of size n is the n × n square matrix 237 * with ones on the main diagonal and zeros elsewhere 238 * 239 * @param Matrix|array $matrix The matrix whose identity we wish to calculate 240 * @return Matrix 241 * @throws Exception 242 **/ 243 public static function identity($matrix) 244 { 245 $matrix = self::validateMatrix($matrix); 246 247 if (!$matrix->isSquare()) { 248 throw new Exception('Identity can only be created for a square matrix'); 249 } 250 251 $dimensions = $matrix->rows; 252 253 return Builder::createIdentityMatrix($dimensions); 254 } 255 256 /** 257 * Return the inverse of this matrix 258 * 259 * @param Matrix|array $matrix The matrix whose inverse we wish to calculate 260 * @return Matrix 261 * @throws Exception 262 **/ 263 public static function inverse($matrix, string $type = 'inverse') 264 { 265 $matrix = self::validateMatrix($matrix); 266 267 if (!$matrix->isSquare()) { 268 throw new Exception(ucfirst($type) . ' can only be calculated for a square matrix'); 269 } 270 271 $determinant = self::getDeterminant($matrix); 272 if ($determinant == 0.0) { 273 throw new Div0Exception(ucfirst($type) . ' can only be calculated for a matrix with a non-zero determinant'); 274 } 275 276 if ($matrix->rows == 1) { 277 return new Matrix([[1 / $matrix->getValue(1, 1)]]); 278 } 279 280 return self::getAdjoint($matrix) 281 ->multiply(1 / $determinant); 282 } 283 284 /** 285 * Calculate the minors of the matrix 286 * 287 * @param Matrix $matrix The matrix whose minors we wish to calculate 288 * @return array[] 289 * 290 * @throws Exception 291 */ 292 protected static function getMinors(Matrix $matrix) 293 { 294 $minors = $matrix->toArray(); 295 $dimensions = $matrix->rows; 296 if ($dimensions == 1) { 297 return $minors; 298 } 299 300 for ($i = 0; $i < $dimensions; ++$i) { 301 for ($j = 0; $j < $dimensions; ++$j) { 302 $minors[$i][$j] = self::getDeterminantSegment($matrix, $i, $j); 303 } 304 } 305 306 return $minors; 307 } 308 309 /** 310 * Return the minors of the matrix 311 * The minor of a matrix A is the determinant of some smaller square matrix, cut down from A by removing one or 312 * more of its rows or columns. 313 * Minors obtained by removing just one row and one column from square matrices (first minors) are required for 314 * calculating matrix cofactors, which in turn are useful for computing both the determinant and inverse of 315 * square matrices. 316 * 317 * @param Matrix|array $matrix The matrix whose minors we wish to calculate 318 * @return Matrix 319 * @throws Exception 320 **/ 321 public static function minors($matrix) 322 { 323 $matrix = self::validateMatrix($matrix); 324 325 if (!$matrix->isSquare()) { 326 throw new Exception('Minors can only be calculated for a square matrix'); 327 } 328 329 return new Matrix(self::getMinors($matrix)); 330 } 331 332 /** 333 * Return the trace of this matrix 334 * The trace is defined as the sum of the elements on the main diagonal (the diagonal from the upper left to the lower right) 335 * of the matrix 336 * 337 * @param Matrix|array $matrix The matrix whose trace we wish to calculate 338 * @return float 339 * @throws Exception 340 **/ 341 public static function trace($matrix) 342 { 343 $matrix = self::validateMatrix($matrix); 344 345 if (!$matrix->isSquare()) { 346 throw new Exception('Trace can only be extracted from a square matrix'); 347 } 348 349 $dimensions = $matrix->rows; 350 $result = 0; 351 for ($i = 1; $i <= $dimensions; ++$i) { 352 $result += $matrix->getValue($i, $i); 353 } 354 355 return $result; 356 } 357 358 /** 359 * Return the transpose of this matrix 360 * 361 * @param Matrix|\a $matrix The matrix whose transpose we wish to calculate 362 * @return Matrix 363 **/ 364 public static function transpose($matrix) 365 { 366 $matrix = self::validateMatrix($matrix); 367 368 $array = array_values(array_merge([null], $matrix->toArray())); 369 $grid = call_user_func_array( 370 'array_map', 371 $array 372 ); 373 374 return new Matrix($grid); 375 } 376 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body