PocketMine-MP 5.19.1 git-f1b1a7022d7dc67d012d8891bc4c23c2652c825e
Matrix.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20*/
21
22declare(strict_types=1);
23
24namespace pocketmine\math;
25
26use function implode;
27use function max;
28use function substr;
29
33class Matrix implements \ArrayAccess{
35 private array $matrix = [];
36 private int $rows;
37 private int $columns;
38
39 public function offsetExists($offset) : bool{
40 return isset($this->matrix[(int) $offset]);
41 }
42
43 #[\ReturnTypeWillChange]
44 public function offsetGet($offset){
45 return $this->matrix[(int) $offset];
46 }
47
48 public function offsetSet($offset, $value) : void{
49 $this->matrix[(int) $offset] = $value;
50 }
51
52 public function offsetUnset($offset) : void{
53 unset($this->matrix[(int) $offset]);
54 }
55
59 public function __construct(int $rows, int $columns, array $set = []){
60 $this->rows = max(1, $rows);
61 $this->columns = max(1, $columns);
62 $this->set($set);
63 }
64
68 public function set(array $m) : void{
69 for($r = 0; $r < $this->rows; ++$r){
70 $this->matrix[$r] = [];
71 for($c = 0; $c < $this->columns; ++$c){
72 $this->matrix[$r][$c] = $m[$r][$c] ?? 0;
73 }
74 }
75 }
76
77 public function getRows() : int{
78 return $this->rows;
79 }
80
81 public function getColumns() : int{
82 return $this->columns;
83 }
84
85 public function setElement(int $row, int $column, float $value) : void{
86 if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){
87 throw new \InvalidArgumentException("Row or column out of bounds (have $this->rows rows $this->columns columns)");
88 }
89 $this->matrix[$row][$column] = $value;
90 }
91
92 public function getElement(int $row, int $column) : float{
93 if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){
94 throw new \InvalidArgumentException("Row or column out of bounds (have $this->rows rows $this->columns columns)");
95 }
96
97 return $this->matrix[$row][$column];
98 }
99
100 public function isSquare() : bool{
101 return $this->rows === $this->columns;
102 }
103
104 public function add(Matrix $matrix) : Matrix{
105 if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){
106 throw new \InvalidArgumentException("Matrix does not have the same number of rows and/or columns");
107 }
108 $result = new Matrix($this->rows, $this->columns);
109 for($r = 0; $r < $this->rows; ++$r){
110 for($c = 0; $c < $this->columns; ++$c){
111 $element = $matrix->getElement($r, $c);
112 $result->setElement($r, $c, $this->matrix[$r][$c] + $element);
113 }
114 }
115
116 return $result;
117 }
118
119 public function subtract(Matrix $matrix) : Matrix{
120 if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){
121 throw new \InvalidArgumentException("Matrix does not have the same number of rows and/or columns");
122 }
123 $result = clone $this;
124 for($r = 0; $r < $this->rows; ++$r){
125 for($c = 0; $c < $this->columns; ++$c){
126 $element = $matrix->getElement($r, $c);
127 $result->setElement($r, $c, $this->matrix[$r][$c] - $element);
128 }
129 }
130
131 return $result;
132 }
133
134 public function multiplyScalar(float $number) : Matrix{
135 $result = clone $this;
136 for($r = 0; $r < $this->rows; ++$r){
137 for($c = 0; $c < $this->columns; ++$c){
138 $result->setElement($r, $c, $this->matrix[$r][$c] * $number);
139 }
140 }
141
142 return $result;
143 }
144
145 public function divideScalar(float $number) : Matrix{
146 $result = clone $this;
147 for($r = 0; $r < $this->rows; ++$r){
148 for($c = 0; $c < $this->columns; ++$c){
149 $result->setElement($r, $c, $this->matrix[$r][$c] / $number);
150 }
151 }
152
153 return $result;
154 }
155
156 public function transpose() : Matrix{
157 $result = new Matrix($this->columns, $this->rows);
158 for($r = 0; $r < $this->rows; ++$r){
159 for($c = 0; $c < $this->columns; ++$c){
160 $result->setElement($c, $r, $this->matrix[$r][$c]);
161 }
162 }
163
164 return $result;
165 }
166
170 public function product(Matrix $matrix) : Matrix{
171 if($this->columns !== $matrix->getRows()){
172 throw new \InvalidArgumentException("Expected a matrix with $this->columns rows"); //????
173 }
174 $c = $matrix->getColumns();
175 $result = new Matrix($this->rows, $c);
176 for($i = 0; $i < $this->rows; ++$i){
177 for($j = 0; $j < $c; ++$j){
178 $sum = 0;
179 for($k = 0; $k < $this->columns; ++$k){
180 $sum += $this->matrix[$i][$k] * $matrix->getElement($k, $j);
181 }
182 $result->setElement($i, $j, $sum);
183 }
184 }
185
186 return $result;
187 }
188
192 public function determinant() : float{
193 if($this->isSquare() !== true){
194 throw new \LogicException("Cannot calculate determinant of a non-square matrix");
195 }
196 return match($this->rows){
197 1 => $this->matrix[0][0],
198 2 =>
199 $this->matrix[0][0] * $this->matrix[1][1] -
200 $this->matrix[0][1] * $this->matrix[1][0],
201 3 =>
202 $this->matrix[0][0] * $this->matrix[1][1] * $this->matrix[2][2] +
203 $this->matrix[0][1] * $this->matrix[1][2] * $this->matrix[2][0] +
204 $this->matrix[0][2] * $this->matrix[1][0] * $this->matrix[2][1] -
205 $this->matrix[2][0] * $this->matrix[1][1] * $this->matrix[0][2] -
206 $this->matrix[2][1] * $this->matrix[1][2] * $this->matrix[0][0] -
207 $this->matrix[2][2] * $this->matrix[1][0] * $this->matrix[0][1],
208 default => throw new \LogicException("Not implemented")
209 };
210 }
211
212 public function __toString() : string{
213 $s = "";
214 for($r = 0; $r < $this->rows; ++$r){
215 $s .= implode(",", $this->matrix[$r]) . ";";
216 }
217
218 return "Matrix({$this->rows}x{$this->columns};" . substr($s, 0, -1) . ")";
219 }
220
221}
product(Matrix $matrix)
Definition: Matrix.php:170
__construct(int $rows, int $columns, array $set=[])
Definition: Matrix.php:59