PluginProbe
TablePress – Tables in WordPress made easy / 2.0.4
TablePress – Tables in WordPress made easy v2.0.4
3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 All 44 releases
tablepress / libraries / vendor / Matrix / Functions.php

Functions.php in TablePress – Tables in WordPress made easy 2.0.4, at libraries/vendor/Matrix/Functions.php

377 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\Matrix;
4
5 class Functions
6 {
7 /**
8 * Validates an array of matrix, converting an array to a matrix if required.
9 *
10 * @param TablePress\Matrix|array $matrix TablePress\Matrix or an array to treat as a matrix.
11 * @return TablePress\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 TablePress\Matrix or array');
21 }
22
23 return $matrix;
24 }
25
26 /**
27 * Calculate the adjoint of the matrix
28 *
29 * @param TablePress\Matrix $matrix The matrix whose adjoint we wish to calculate
30 * @return TablePress\Matrix
31 *
32 * @throws Exception
33 */
34 private static function getAdjoint(TablePress\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 TablePress\Matrix|array $matrix The matrix whose adjoint we wish to calculate
48 * @return TablePress\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 TablePress\Matrix $matrix The matrix whose cofactors we wish to calculate
66 * @return TablePress\Matrix
67 *
68 * @throws Exception
69 */
70 private static function getCofactors(TablePress\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 TablePress\Matrix|array $matrix The matrix whose cofactors we wish to calculate
92 * @return TablePress\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 TablePress\Matrix $matrix
109 * @param int $row
110 * @param int $column
111 * @return float
112 * @throws Exception
113 */
114 private static function getDeterminantSegment(TablePress\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 TablePress\Matrix $matrix The matrix whose determinant we wish to calculate
132 * @return float
133 *
134 * @throws Exception
135 */
136 private static function getDeterminant(TablePress\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 TablePress\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 TablePress\Matrix|array $matrix The matrix whose diagonal we wish to calculate
186 * @return TablePress\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 TablePress\Matrix|array $matrix The matrix whose antidiagonal we wish to calculate
212 * @return TablePress\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 TablePress\Matrix|array $matrix The matrix whose identity we wish to calculate
240 * @return TablePress\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 TablePress\Matrix|array $matrix The matrix whose inverse we wish to calculate
260 * @return TablePress\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 TablePress\Matrix $matrix The matrix whose minors we wish to calculate
288 * @return array[]
289 *
290 * @throws Exception
291 */
292 protected static function getMinors(TablePress\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 TablePress\Matrix|array $matrix The matrix whose minors we wish to calculate
318 * @return TablePress\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 TablePress\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 TablePress\Matrix|\a $matrix The matrix whose transpose we wish to calculate
362 * @return TablePress\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 }
377