ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Matrix.php
Go to the documentation of this file.
1<?php
2
11namespace Matrix;
12
13use Generator;
16
42class Matrix
43{
44 protected $rows;
45 protected $columns;
46 protected $grid = [];
47
48 /*
49 * Create a new Matrix object from an array of values
50 *
51 * @param array $grid
52 */
53 final public function __construct(array $grid)
54 {
55 $this->buildFromArray(array_values($grid));
56 }
57
58 /*
59 * Create a new Matrix object from an array of values
60 *
61 * @param array $grid
62 */
63 protected function buildFromArray(array $grid): void
64 {
65 $this->rows = count($grid);
66 $columns = array_reduce(
67 $grid,
68 function ($carry, $value) {
69 return max($carry, is_array($value) ? count($value) : 1);
70 }
71 );
72 $this->columns = $columns;
73
74 array_walk(
75 $grid,
76 function (&$value) use ($columns) {
77 if (!is_array($value)) {
78 $value = [$value];
79 }
80 $value = array_pad(array_values($value), $columns, null);
81 }
82 );
83
84 $this->grid = $grid;
85 }
86
94 public static function validateRow(int $row): int
95 {
96 if ((!is_numeric($row)) || (intval($row) < 1)) {
97 throw new Exception('Invalid Row');
98 }
99
100 return (int)$row;
101 }
102
110 public static function validateColumn(int $column): int
111 {
112 if ((!is_numeric($column)) || (intval($column) < 1)) {
113 throw new Exception('Invalid Column');
114 }
115
116 return (int)$column;
117 }
118
126 protected function validateRowInRange(int $row): int
127 {
128 $row = static::validateRow($row);
129 if ($row > $this->rows) {
130 throw new Exception('Requested Row exceeds matrix size');
131 }
132
133 return $row;
134 }
135
143 protected function validateColumnInRange(int $column): int
144 {
145 $column = static::validateColumn($column);
146 if ($column > $this->columns) {
147 throw new Exception('Requested Column exceeds matrix size');
148 }
149
150 return $column;
151 }
152
165 public function getRows(int $row, int $rowCount = 1): Matrix
166 {
167 $row = $this->validateRowInRange($row);
168 if ($rowCount === 0) {
169 $rowCount = $this->rows - $row + 1;
170 }
171
172 return new static(array_slice($this->grid, $row - 1, (int)$rowCount));
173 }
174
187 public function getColumns(int $column, int $columnCount = 1): Matrix
188 {
189 $column = $this->validateColumnInRange($column);
190 if ($columnCount < 1) {
191 $columnCount = $this->columns + $columnCount - $column + 1;
192 }
193
194 $grid = [];
195 for ($i = $column - 1; $i < $column + $columnCount - 1; ++$i) {
196 $grid[] = array_column($this->grid, $i);
197 }
198
199 return (new static($grid))->transpose();
200 }
201
215 public function dropRows(int $row, int $rowCount = 1): Matrix
216 {
217 $this->validateRowInRange($row);
218 if ($rowCount === 0) {
219 $rowCount = $this->rows - $row + 1;
220 }
221
223 array_splice($grid, $row - 1, (int)$rowCount);
224
225 return new static($grid);
226 }
227
241 public function dropColumns(int $column, int $columnCount = 1): Matrix
242 {
243 $this->validateColumnInRange($column);
244 if ($columnCount < 1) {
245 $columnCount = $this->columns + $columnCount - $column + 1;
246 }
247
249 array_walk(
250 $grid,
251 function (&$row) use ($column, $columnCount) {
252 array_splice($row, $column - 1, (int)$columnCount);
253 }
254 );
255
256 return new static($grid);
257 }
258
268 public function getValue(int $row, int $column)
269 {
270 $row = $this->validateRowInRange($row);
271 $column = $this->validateColumnInRange($column);
272
273 return $this->grid[$row - 1][$column - 1];
274 }
275
282 public function rows(): Generator
283 {
284 foreach ($this->grid as $i => $row) {
285 yield $i + 1 => ($this->columns == 1)
286 ? $row[0]
287 : new static([$row]);
288 }
289 }
290
297 public function columns(): Generator
298 {
299 for ($i = 0; $i < $this->columns; ++$i) {
300 yield $i + 1 => ($this->rows == 1)
301 ? $this->grid[0][$i]
302 : new static(array_column($this->grid, $i));
303 }
304 }
305
312 public function isSquare(): bool
313 {
314 return $this->rows === $this->columns;
315 }
316
323 public function isVector(): bool
324 {
325 return $this->rows === 1 || $this->columns === 1;
326 }
327
333 public function toArray(): array
334 {
335 return $this->grid;
336 }
337
347 public function solve(Matrix $B): Matrix
348 {
349 if ($this->columns === $this->rows) {
350 return (new LU($this))->solve($B);
351 }
352
353 return (new QR($this))->solve($B);
354 }
355
356 protected static $getters = [
357 'rows',
358 'columns',
359 ];
360
368 public function __get(string $propertyName)
369 {
370 $propertyName = strtolower($propertyName);
371
372 // Test for function calls
373 if (in_array($propertyName, self::$getters)) {
374 return $this->$propertyName;
375 }
376
377 throw new Exception('Property does not exist');
378 }
379
380 protected static $functions = [
381 'adjoint',
382 'antidiagonal',
383 'cofactors',
384 'determinant',
385 'diagonal',
386 'identity',
387 'inverse',
388 'minors',
389 'trace',
390 'transpose',
391 ];
392
393 protected static $operations = [
394 'add',
395 'subtract',
396 'multiply',
397 'divideby',
398 'divideinto',
399 'directsum',
400 ];
401
410 public function __call(string $functionName, $arguments)
411 {
412 $functionName = strtolower(str_replace('_', '', $functionName));
413
414 if (in_array($functionName, self::$functions, true) || in_array($functionName, self::$operations, true)) {
415 $functionName = "\\" . __NAMESPACE__ . "\\{$functionName}";
416 if (is_callable($functionName)) {
417 $arguments = array_values(array_merge([$this], $arguments));
418 return call_user_func_array($functionName, $arguments);
419 }
420 }
421 throw new Exception('Function or Operation does not exist');
422 }
423}
if(! $in) $columns
Definition: Utf8Test.php:45
An exception for terminatinating execution or to throw for unit testing.
validateColumnInRange(int $column)
Validate that a column number falls within the set of columns for this matrix.
Definition: Matrix.php:143
static validateColumn(int $column)
Validate that a column number is a positive integer.
Definition: Matrix.php:110
isSquare()
Identify if the row and column dimensions of this matrix are equal, i.e.
Definition: Matrix.php:312
dropColumns(int $column, int $columnCount=1)
Return a new matrix as a subset of columns from this matrix, dropping columns starting at column numb...
Definition: Matrix.php:241
static validateRow(int $row)
Validate that a row number is a positive integer.
Definition: Matrix.php:94
getColumns(int $column, int $columnCount=1)
Return a new matrix as a subset of columns from this matrix, starting at column number $column,...
Definition: Matrix.php:187
buildFromArray(array $grid)
Definition: Matrix.php:63
__call(string $functionName, $arguments)
Returns the result of the function call or operation.
Definition: Matrix.php:410
getRows(int $row, int $rowCount=1)
Return a new matrix as a subset of rows from this matrix, starting at row number $row,...
Definition: Matrix.php:165
__get(string $propertyName)
Access specific properties as read-only (no setters)
Definition: Matrix.php:368
rows()
Returns a Generator that will yield each row of the matrix in turn as a vector matrix or the value of...
Definition: Matrix.php:282
__construct(array $grid)
Definition: Matrix.php:53
dropRows(int $row, int $rowCount=1)
Return a new matrix as a subset of rows from this matrix, dropping rows starting at row number $row,...
Definition: Matrix.php:215
isVector()
Identify if this matrix is a vector i.e.
Definition: Matrix.php:323
solve(Matrix $B)
Solve A*X = B.
Definition: Matrix.php:347
toArray()
Return the matrix as a 2-dimensional array.
Definition: Matrix.php:333
validateRowInRange(int $row)
Validate that a row number falls within the set of rows for this matrix.
Definition: Matrix.php:126
getValue(int $row, int $column)
Return a value from this matrix, from the "cell" identified by the row and column numbers Note that r...
Definition: Matrix.php:268
columns()
Returns a Generator that will yield each column of the matrix in turn as a vector matrix or the value...
Definition: Matrix.php:297
$i
Definition: disco.tpl.php:19
$grid
Definition: test.php:8
$row
if(! $row) $columnCount
Class for the creating "special" Matrices.
Definition: Builder.php:11