35 private array $matrix = [];
39 public function offsetExists($offset) :
bool{
40 return isset($this->matrix[(
int) $offset]);
43 #[\ReturnTypeWillChange]
44 public function offsetGet($offset){
45 return $this->matrix[(int) $offset];
48 public function offsetSet($offset, $value) :
void{
49 $this->matrix[(int) $offset] = $value;
52 public function offsetUnset($offset) :
void{
53 unset($this->matrix[(
int) $offset]);
59 public function __construct(
int $rows,
int $columns, array $set = []){
60 $this->rows = max(1, $rows);
61 $this->columns = max(1, $columns);
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;
77 public function getRows() : int{
81 public function getColumns() : int{
82 return $this->columns;
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)");
89 $this->matrix[$row][$column] = $value;
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)");
97 return $this->matrix[$row][$column];
100 public function isSquare() : bool{
101 return $this->rows === $this->columns;
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");
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);
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");
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);
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);
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);
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]);
171 if($this->columns !== $matrix->getRows()){
172 throw new \InvalidArgumentException(
"Expected a matrix with $this->columns rows");
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){
179 for($k = 0; $k < $this->columns; ++$k){
180 $sum += $this->matrix[$i][$k] * $matrix->getElement($k, $j);
182 $result->setElement($i, $j, $sum);
193 if($this->isSquare() !== true){
194 throw new \LogicException(
"Cannot calculate determinant of a non-square matrix");
196 return match($this->rows){
197 1 => $this->matrix[0][0],
199 $this->matrix[0][0] * $this->matrix[1][1] -
200 $this->matrix[0][1] * $this->matrix[1][0],
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")
212 public function __toString() : string{
214 for($r = 0; $r < $this->rows; ++$r){
215 $s .= implode(
",", $this->matrix[$r]) .
";";
218 return "Matrix({$this->rows}x{$this->columns};" . substr($s, 0, -1) .
")";