Yet Another Game Engine
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matrix.h
Go to the documentation of this file.
1 
10 #pragma once
11 
12 #include <algorithm>
13 #include <exception>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17 
18 namespace yage
19 {
20 
21 template <int Rows, int Cols, class Type>
22 class Matrix;
23 
31 namespace details
32 {
33 
42 template <int Rows, int Cols, class Type>
43 class Row
44 {
45 private:
46  Matrix<Rows, Cols, Type> *parent_;
47  int index_;
48 
49 public:
51  : parent_(parent), index_(index)
52  {
53  }
54 
55  Type &operator[](int col)
56  {
57  // The index is the y-position of the element in the matrix
58  return parent_->data_[index_ * Cols + col];
59  }
60 
61  const Type &operator[](int col) const
62  {
63  return parent_->data_[index_ * Cols + col];
64  }
65 };
66 
67 } // namespace details
68 
71 template <int Rows = 4, int Cols = 4, class Type = double>
72 class Matrix
73 {
74  // friended with the row class so that it can access protected member data.
75  friend class details::Row<Rows, Cols, Type>;
76 
77 protected:
79  std::vector<Type> data_;
80 
81 public:
83  Matrix<Rows, Cols, Type>() : data_(Rows * Cols) {}
84  Matrix<Rows, Cols, Type>(const std::vector<Type> &data) : data_(data) {}
85 
87  int rowSize() const { return Rows; }
88 
90  int colSize() const { return Cols; }
91 
98  {
99  Matrix<1, Cols, Type> rowMatrix;
100  for (int i = 0; i < Cols; ++i) {
101  rowMatrix[0][i] = data_[row][i];
102  }
103  return rowMatrix;
104  }
105 
112  {
113  Matrix<Rows, 1, Type> colMatrix;
114  for (int i = 0; i < Rows; ++i) {
115  colMatrix[i][0] = data_[i][col];
116  }
117  return colMatrix;
118  }
119 
124  typename std::vector<Type>::iterator begin() { return data_.begin(); }
125 
130  typename std::vector<Type>::iterator end() { return data_.end(); }
131 
138  virtual std::string toString() const
139  {
140  std::stringstream ss;
141  ss << '[';
142  for (int i = 0; i < Rows - 1; ++i) {
143  ss << '[';
144  for (int j = 0; j < Cols - 1; ++j) {
145  ss << data_[i * Cols + j] << ' ';
146  }
147  ss << data_[(Rows - 1) * Cols + Cols - 1] << "],";
148  }
149  ss << '[';
150  for (int j = 0; j < Cols - 1; ++j) {
151  ss << data_[(Rows - 1) * Cols + j] << ' ';
152  }
153  ss << data_[(Rows - 1) * Cols + Cols - 1] << "]]";
154  return ss.str();
155  }
156 
158  {
159  return details::Row<Rows, Cols, Type>(this, row);
160  }
161 
163  {
165  row);
166  }
167 
169  {
170  std::vector<Type> out;
171  out.reserve(data_.size());
172  std::transform(data_.begin(), data_.end(), rhs.data_.begin(),
173  std::back_inserter(out),
174  [](Type a, Type b) { return a + b; });
175  data_ = std::move(out);
176  return *this;
177  }
178 
180  {
181  std::vector<Type> out;
182  out.reserve(data_.size());
183  std::transform(data_.begin(), data_.end(), rhs.begin(),
184  std::back_inserter(out),
185  [](Type a, Type b) { return a - b; });
186  data_ = std::move(out);
187  return *this;
188  }
189 };
190 
191 template <int M, int N, class T>
193 {
194  lhs += rhs;
195  return lhs;
196 }
197 
198 template <int M, int N, class T>
200 {
201  lhs -= rhs;
202  return lhs;
203 }
204 
205 template <int M, int N, class T>
207 {
208  for (auto &data : lhs) {
209  data += rhs;
210  }
211  return lhs;
212 }
213 
214 template <int M, int N, class T>
216 {
217  for (auto &data : rhs) {
218  data += lhs;
219  }
220  return rhs;
221 }
222 
223 template <int M, int N, class T>
225 {
226  for (auto &data : lhs) {
227  data -= rhs;
228  }
229  return lhs;
230 }
231 
232 template <int M, int N, class T>
234 {
235  for (auto &data : rhs) {
236  data = lhs - data;
237  }
238  return rhs;
239 }
240 
241 template <int M, int N, class T>
243 {
244  for (auto &data : lhs) {
245  data *= rhs;
246  }
247  return lhs;
248 }
249 
250 template <int M, int N, class T>
252 {
253  for (auto &data : rhs) {
254  data *= lhs;
255  }
256  return rhs;
257 }
258 
259 template <int M, int N, class T>
261 {
262  for (auto &data : lhs) {
263  data /= rhs;
264  }
265  return lhs;
266 }
267 
268 template <int M, int N, class T>
269 bool operator==(const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs)
270 {
271  for (int i = 0; i < M; ++i) {
272  for (int j = 0; j < N; ++j) {
273  if (lhs[i][j] != rhs[i][j]) {
274  return false;
275  }
276  }
277  }
278  return true;
279 }
280 
281 template <int M, int N, class T>
282 std::ostream &operator<<(std::ostream &os, const Matrix<M, N, T> &mat)
283 {
284  return os << mat.toString();
285 }
286 
287 template <int Rows = 2, class Type = double>
288 class Vector : public Matrix<Rows, 1, Type>
289 {
290 public:
293  : Matrix<Rows, 1, Type>(other)
294  {
295  }
296 
297  Vector<Rows, Type>(const std::vector<Type> &data)
298  : Matrix<Rows, 1, Type>(data)
299  {
300  }
301 
302  Type &operator[](int col) { return this->data_[col]; }
303 
304  const Type &operator[](int col) const { return this->data_[col]; }
305 
306  std::string toString() const override
307  {
308  std::stringstream ss;
309  ss << "[";
310  for (std::size_t i = 0; i < this->data_.size() - 1; ++i) {
311  ss << this->data_[i] << " ";
312  }
313  ss << this->data_[this->data_.size() - 1] << "]";
314  return ss.str();
315  }
316 };
317 
322 template <typename Type = double>
323 class Vector2 : public Vector<2, Type>
324 {
325 public:
327  Vector2<Type>(const std::vector<Type> &data) : Vector<2, Type>(data) {}
328 
329  Vector2<Type>(Type x, Type y)
330  {
331  this->data_[0] = x;
332  this->data_[1] = y;
333  }
334 
336 
337  Type &x() { return this->data_[0]; }
338  const Type &x() const { return this->data_[0]; }
339 
340  Type &y() { return this->data_[1]; }
341  const Type &y() const { return this->data_[1]; }
342 };
343 
348 template <typename Type = double>
349 class Vector3 : public Vector<3, Type>
350 {
351 public:
352  Type &x, &y, &z;
353 
355 
356  Vector3<Type>(std::vector<Type> data)
357  : Vector<3, Type>(data), x(this->data_[0]), y(this->data_[1]),
358  z(this->data_[2])
359  {
360  }
361 
362  Vector3<Type>(Type x_in, Type y_in, Type z_in)
363  : Vector<3, Type>({x_in, y_in, z_in}), x(this->data_[0]),
364  y(this->data_[1]), z(this->data_[2])
365  {
366  }
367 };
368 
371 template <typename Type = double>
372 class Vector4 : public Vector<4, Type>
373 {
374 public:
375  Type &x, &y, &z, &w;
376 
378 
379  Vector4<Type>(std::vector<Type> data)
380  : Vector<4, Type>(data), x(this->data_[0]), y(this->data_[1]),
381  z(this->data_[2]), w(this->data_[3])
382  {
383  }
384 
385  Vector4<Type>(Type x_in, Type y_in, Type z_in, Type w_in)
386  : Vector<4, Type>({x_in, y_in, z_in, w_in}), x(this->data_[0]),
387  y(this->data_[1]), z(this->data_[2]), w(this->data_[3])
388  {
389  }
390 };
391 
397 
403 
409 
415 namespace matrix
416 {
417 
422 template <int M, int N, class T>
424 {
425  Matrix<N, M, T> trans;
426  for (int i = 0; i < M; ++i) {
427  for (int j = 0; j < N; ++j) {
428  trans[j][i] = m[i][j];
429  }
430  }
431  return trans;
432 }
433 
438 template <int R, class T>
439 T dot(const Matrix<R, 1, T> &m1, const Matrix<R, 1, T> &m2)
440 {
441  T sum = 0;
442  for (int i = 0; i < R; ++i) {
443  sum += m1[i][0] * m2[i][0];
444  }
445  return sum;
446 }
447 
454 template <int M, int N, int P, int Q, class T>
456 {
458  if (N != P) {
459  throw std::runtime_error(
460  "Matrices don't have the right dimensions for multiplication");
461  }
462 
463  Matrix<M, Q, T> res;
464 
467  for (int i = 0; i < M; ++i) {
468  for (int j = 0; j < Q; ++j) {
469  res[i][j] = dot(transpose(m1.getRow(i)), m2.getCol(j));
470  }
471  }
472 
473  return res;
474 }
475 
476 } // namespace matrix
477 
478 } // namespace yage
Matrix< M, N, T > operator/(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:260
Matrix< 1, Cols, Type > getRow(int row) const
Return the row specified row as a Matrix with only one row.
Definition: matrix.h:97
Type & z
Definition: matrix.h:375
Definition: matrix.h:43
Matrix< M, N, T > operator*(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:242
int rowSize() const
Returns the row size of the Matrix.
Definition: matrix.h:87
z(this->data_[2])
Definition: matrix.h:364
2D Vector class.
Definition: matrix.h:323
bool operator==(const Matrix< M, N, T > &lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:269
Type & y
Definition: matrix.h:352
std::vector< Type >::iterator end()
Iterator support for the end.
Definition: matrix.h:130
Type & x
Definition: matrix.h:352
Type & operator[](int col)
Definition: matrix.h:302
Type & y
Definition: matrix.h:375
std::vector< Type > data_
Vector containing the data of the matrix.
Definition: matrix.h:79
Matrix< M, Q, T > multiply(const Matrix< M, N, T > &m1, const Matrix< P, Q, T > &m2)
Multiplies two matrices together.
Definition: matrix.h:455
Type & y()
Definition: matrix.h:340
Type & operator[](int col)
Definition: matrix.h:55
Matrix< Rows, 1, Type > getCol(int col) const
Get a specific column in a column vector.
Definition: matrix.h:111
const Type & operator[](int col) const
Definition: matrix.h:61
w(this->data_[3])
Definition: matrix.h:387
const Type & x() const
Definition: matrix.h:338
Type & x
Definition: matrix.h:375
Matrix< N, M, T > transpose(const Matrix< M, N, T > &m)
Transposes a matrix and returns the result.
Definition: matrix.h:423
int colSize() const
Returns the column size of the Matrix.
Definition: matrix.h:90
const Type & operator[](int col) const
Definition: matrix.h:304
Matrix< Rows, Cols, Type > & operator-=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:179
3D Vector class.
Definition: matrix.h:349
Type & x()
Definition: matrix.h:337
details::Row< Rows, Cols, Type > operator[](int row) const
Definition: matrix.h:162
details::Row< Rows, Cols, Type > operator[](int row)
Definition: matrix.h:157
Matrix< M, N, T > operator+(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:192
Definition: matrix.h:288
Matrix< M, N, T > operator-(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:199
virtual std::string toString() const
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:138
Matrix< Rows, Cols, Type > & operator+=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:168
Base Matrix class used by other similar classes.
Definition: matrix.h:22
T dot(const Matrix< R, 1, T > &m1, const Matrix< R, 1, T > &m2)
Returns the dot product between two vectors.
Definition: matrix.h:439
Type & w
Definition: matrix.h:375
const Type & y() const
Definition: matrix.h:341
std::string toString() const override
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:306
4D Vector class
Definition: matrix.h:372
std::vector< Type >::iterator begin()
Iterator support for the start.
Definition: matrix.h:124
Type & z
Definition: matrix.h:352