PocketMine-MP  1.4 - API 1.10.0
 All Classes Namespaces Functions Variables Pages
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 
22 namespace pocketmine\math;
23 
24 
25 class Matrix implements \ArrayAccess{
26  private $matrix = [];
27  private $rows = 0;
28  private $columns = 0;
29 
30  public function offsetExists($offset){
31  return isset($this->matrix[(int) $offset]);
32  }
33 
34  public function offsetGet($offset){
35  return $this->matrix[(int) $offset];
36  }
37 
38  public function offsetSet($offset, $value){
39  $this->matrix[(int) $offset] = $value;
40  }
41 
42  public function offsetUnset($offset){
43  unset($this->matrix[(int) $offset]);
44  }
45 
46  public function __construct($rows, $columns, array $set = []){
47  $this->rows = max(1, (int) $rows);
48  $this->columns = max(1, (int) $columns);
49  $this->set($set);
50  }
51 
52  public function set(array $m){
53  for($r = 0; $r < $this->rows; ++$r){
54  $this->matrix[$r] = [];
55  for($c = 0; $c < $this->columns; ++$c){
56  $this->matrix[$r][$c] = isset($m[$r][$c]) ? $m[$r][$c] : 0;
57  }
58  }
59  }
60 
61  public function getRows(){
62  return ($this->rows);
63  }
64 
65  public function getColumns(){
66  return ($this->columns);
67  }
68 
69  public function setElement($row, $column, $value){
70  if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){
71  return false;
72  }
73  $this->matrix[(int) $row][(int) $column] = $value;
74 
75  return true;
76  }
77 
78  public function getElement($row, $column){
79  if($row > $this->rows or $row < 0 or $column > $this->columns or $column < 0){
80  return false;
81  }
82 
83  return $this->matrix[(int) $row][(int) $column];
84  }
85 
86  public function isSquare(){
87  return $this->rows === $this->columns;
88  }
89 
90  public function add(Matrix $matrix){
91  if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){
92  return false;
93  }
94  $result = new Matrix($this->rows, $this->columns);
95  for($r = 0; $r < $this->rows; ++$r){
96  for($c = 0; $c < $this->columns; ++$c){
97  $result->setElement($r, $c, $this->matrix[$r][$c] + $matrix->getElement($r, $c));
98  }
99  }
100 
101  return $result;
102  }
103 
104  public function substract(Matrix $matrix){
105  if($this->rows !== $matrix->getRows() or $this->columns !== $matrix->getColumns()){
106  return false;
107  }
108  $result = clone $this;
109  for($r = 0; $r < $this->rows; ++$r){
110  for($c = 0; $c < $this->columns; ++$c){
111  $result->setElement($r, $c, $this->matrix[$r][$c] - $matrix->getElement($r, $c));
112  }
113  }
114 
115  return $result;
116  }
117 
118  public function multiplyScalar($number){
119  $result = clone $this;
120  for($r = 0; $r < $this->rows; ++$r){
121  for($c = 0; $c < $this->columns; ++$c){
122  $result->setElement($r, $c, $this->matrix[$r][$c] * $number);
123  }
124  }
125 
126  return $result;
127  }
128 
129 
130  public function divideScalar($number){
131  $result = clone $this;
132  for($r = 0; $r < $this->rows; ++$r){
133  for($c = 0; $c < $this->columns; ++$c){
134  $result->setElement($r, $c, $this->matrix[$r][$c] / $number);
135  }
136  }
137 
138  return $result;
139  }
140 
141  public function transpose(){
142  $result = new Matrix($this->columns, $this->rows);
143  for($r = 0; $r < $this->rows; ++$r){
144  for($c = 0; $c < $this->columns; ++$c){
145  $result->setElement($c, $r, $this->matrix[$r][$c]);
146  }
147  }
148 
149  return $result;
150  }
151 
152  //Naive Matrix product, O(n^3)
153  public function product(Matrix $matrix){
154  if($this->columns !== $matrix->getRows()){
155  return false;
156  }
157  $c = $matrix->getColumns();
158  $result = new Matrix($this->rows, $c);
159  for($i = 0; $i < $this->rows; ++$i){
160  for($j = 0; $j < $c; ++$j){
161  $sum = 0;
162  for($k = 0; $k < $this->columns; ++$k){
163  $sum += $this->matrix[$i][$k] * $matrix->getElement($k, $j);
164  }
165  $result->setElement($i, $j, $sum);
166  }
167  }
168 
169  return $result;
170  }
171 
172 
173  //Computation of the determinant of 2x2 and 3x3 matrices
174  public function determinant(){
175  if($this->isSquare() !== true){
176  return false;
177  }
178  switch($this->rows){
179  case 1:
180  return 0;
181  case 2:
182  return $this->matrix[0][0] * $this->matrix[1][1] - $this->matrix[0][1] * $this->matrix[1][0];
183  case 3:
184  return $this->matrix[0][0] * $this->matrix[1][1] * $this->matrix[2][2] + $this->matrix[0][1] * $this->matrix[1][2] * $this->matrix[2][0] + $this->matrix[0][2] * $this->matrix[1][0] * $this->matrix[2][1] - $this->matrix[2][0] * $this->matrix[1][1] * $this->matrix[0][2] - $this->matrix[2][1] * $this->matrix[1][2] * $this->matrix[0][0] - $this->matrix[2][2] * $this->matrix[1][0] * $this->matrix[0][1];
185  }
186 
187  return false;
188  }
189 
190 
191  public function __toString(){
192  $s = "";
193  for($r = 0; $r < $this->rows; ++$r){
194  $s .= implode(",", $this->matrix[$r]) . ";";
195  }
196 
197  return "Matrix({$this->rows}x{$this->columns};" . substr($s, 0, -1) . ")";
198  }
199 
200 }