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 
12 #pragma once
13 
14 #include <algorithm>
15 #include <exception>
16 #include <iostream>
17 #include <sstream>
18 #include <string>
19 #include <vector>
20 
21 namespace yage
22 {
23 
24 template <int Rows, int Cols, class Type>
25 class Matrix;
26 
34 namespace details
35 {
36 
45 template <int Rows, int Cols, class Type>
46 class Row
47 {
48 private:
49  Matrix<Rows, Cols, Type> *parent_;
50  int index_;
51 
52 public:
54  : parent_(parent), index_(index)
55  {
56  }
57 
58  Type &operator[](int col)
59  {
60  // The index is the y-position of the element in the matrix
61  return parent_->data_[index_ * Cols + col];
62  }
63 
64  const Type &operator[](int col) const
65  {
66  return parent_->data_[index_ * Cols + col];
67  }
68 };
69 
70 } // namespace details
71 
74 template <int Rows = 4, int Cols = 4, class Type = double>
75 class Matrix
76 {
77  // friended with the row class so that it can access protected member data.
78  friend class details::Row<Rows, Cols, Type>;
79 
80 protected:
82  std::vector<Type> data_;
83 
84 public:
86  Matrix<Rows, Cols, Type>() : data_(Rows * Cols) {}
87  Matrix<Rows, Cols, Type>(const std::vector<Type> &data) : data_(data) {}
88 
90  int rowSize() const { return Rows; }
91 
93  int colSize() const { return Cols; }
94 
101  {
102  Matrix<1, Cols, Type> rowMatrix;
103  for (int i = 0; i < Cols; ++i) {
104  rowMatrix[0][i] = data_[row][i];
105  }
106  return rowMatrix;
107  }
108 
115  {
116  Matrix<Rows, 1, Type> colMatrix;
117  for (int i = 0; i < Rows; ++i) {
118  colMatrix[i][0] = data_[i][col];
119  }
120  return colMatrix;
121  }
122 
127  typename std::vector<Type>::iterator begin() { return data_.begin(); }
128 
133  typename std::vector<Type>::iterator end() { return data_.end(); }
134 
141  virtual std::string toString() const
142  {
143  std::stringstream ss;
144  ss << '[';
145  for (int i = 0; i < Rows - 1; ++i) {
146  ss << '[';
147  for (int j = 0; j < Cols - 1; ++j) {
148  ss << data_[i * Cols + j] << ' ';
149  }
150  ss << data_[(Rows - 1) * Cols + Cols - 1] << "],";
151  }
152  ss << '[';
153  for (int j = 0; j < Cols - 1; ++j) {
154  ss << data_[(Rows - 1) * Cols + j] << ' ';
155  }
156  ss << data_[(Rows - 1) * Cols + Cols - 1] << "]]";
157  return ss.str();
158  }
159 
161  {
162  return details::Row<Rows, Cols, Type>(this, row);
163  }
164 
166  {
168  row);
169  }
170 
172  {
173  std::vector<Type> out;
174  out.reserve(data_.size());
175  std::transform(data_.begin(), data_.end(), rhs.data_.begin(),
176  std::back_inserter(out),
177  [](Type a, Type b) { return a + b; });
178  data_ = std::move(out);
179  return *this;
180  }
181 
183  {
184  std::vector<Type> out;
185  out.reserve(data_.size());
186  std::transform(data_.begin(), data_.end(), rhs.begin(),
187  std::back_inserter(out),
188  [](Type a, Type b) { return a - b; });
189  data_ = std::move(out);
190  return *this;
191  }
192 };
193 
194 template <int M, int N, class T>
196 {
197  lhs += rhs;
198  return lhs;
199 }
200 
201 template <int M, int N, class T>
203 {
204  lhs -= rhs;
205  return lhs;
206 }
207 
208 template <int M, int N, class T>
210 {
211  for (auto &data : lhs) {
212  data += rhs;
213  }
214  return lhs;
215 }
216 
217 template <int M, int N, class T>
219 {
220  for (auto &data : rhs) {
221  data += lhs;
222  }
223  return rhs;
224 }
225 
226 template <int M, int N, class T>
228 {
229  for (auto &data : lhs) {
230  data -= rhs;
231  }
232  return lhs;
233 }
234 
235 template <int M, int N, class T>
237 {
238  for (auto &data : rhs) {
239  data = lhs - data;
240  }
241  return rhs;
242 }
243 
244 template <int M, int N, class T>
246 {
247  for (auto &data : lhs) {
248  data *= rhs;
249  }
250  return lhs;
251 }
252 
253 template <int M, int N, class T>
255 {
256  for (auto &data : rhs) {
257  data *= lhs;
258  }
259  return rhs;
260 }
261 
262 template <int M, int N, class T>
264 {
265  for (auto &data : lhs) {
266  data /= rhs;
267  }
268  return lhs;
269 }
270 
271 template <int M, int N, class T>
272 bool operator==(const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs)
273 {
274  for (int i = 0; i < M; ++i) {
275  for (int j = 0; j < N; ++j) {
276  if (lhs[i][j] != rhs[i][j]) {
277  return false;
278  }
279  }
280  }
281  return true;
282 }
283 
284 template <int M, int N, class T>
285 std::ostream &operator<<(std::ostream &os, const Matrix<M, N, T> &mat)
286 {
287  return os << mat.toString();
288 }
289 
290 template <int Rows = 2, class Type = double>
291 class Vector : public Matrix<Rows, 1, Type>
292 {
293 public:
296  : Matrix<Rows, 1, Type>(other)
297  {
298  }
299 
300  Vector<Rows, Type>(const std::vector<Type> &data)
301  : Matrix<Rows, 1, Type>(data)
302  {
303  }
304 
305  Type &operator[](int col) { return this->data_[col]; }
306 
307  const Type &operator[](int col) const { return this->data_[col]; }
308 
309  std::string toString() const override
310  {
311  std::stringstream ss;
312  ss << "[";
313  for (std::size_t i = 0; i < this->data_.size() - 1; ++i) {
314  ss << this->data_[i] << " ";
315  }
316  ss << this->data_[this->data_.size() - 1] << "]";
317  return ss.str();
318  }
319 };
320 
325 template <typename Type = double>
326 class Vector2 : public Vector<2, Type>
327 {
328 public:
330  Vector2<Type>(const std::vector<Type> &data) : Vector<2, Type>(data) {}
331 
332  Vector2<Type>(Type x, Type y)
333  {
334  this->data_[0] = x;
335  this->data_[1] = y;
336  }
337 
339 
340  Type &x() { return this->data_[0]; }
341  const Type &x() const { return this->data_[0]; }
342 
343  Type &y() { return this->data_[1]; }
344  const Type &y() const { return this->data_[1]; }
345 };
346 
351 template <typename Type = double>
352 class Vector3 : public Vector<3, Type>
353 {
354 public:
355  Type &x, &y, &z;
356 
358 
359  Vector3<Type>(std::vector<Type> data)
360  : Vector<3, Type>(data), x(this->data_[0]), y(this->data_[1]),
361  z(this->data_[2])
362  {
363  }
364 
365  Vector3<Type>(Type x_in, Type y_in, Type z_in)
366  : Vector<3, Type>({x_in, y_in, z_in}), x(this->data_[0]),
367  y(this->data_[1]), z(this->data_[2])
368  {
369  }
370 };
371 
374 template <typename Type = double>
375 class Vector4 : public Vector<4, Type>
376 {
377 public:
378  Type &x, &y, &z, &w;
379 
381 
382  Vector4<Type>(std::vector<Type> data)
383  : Vector<4, Type>(data), x(this->data_[0]), y(this->data_[1]),
384  z(this->data_[2]), w(this->data_[3])
385  {
386  }
387 
388  Vector4<Type>(Type x_in, Type y_in, Type z_in, Type w_in)
389  : Vector<4, Type>({x_in, y_in, z_in, w_in}), x(this->data_[0]),
390  y(this->data_[1]), z(this->data_[2]), w(this->data_[3])
391  {
392  }
393 };
394 
400 
406 
412 
418 namespace matrix
419 {
420 
425 template <int M, int N, class T>
427 {
428  Matrix<N, M, T> trans;
429  for (int i = 0; i < M; ++i) {
430  for (int j = 0; j < N; ++j) {
431  trans[j][i] = m[i][j];
432  }
433  }
434  return trans;
435 }
436 
441 template <int R, class T>
442 T dot(const Matrix<R, 1, T> &m1, const Matrix<R, 1, T> &m2)
443 {
444  T sum = 0;
445  for (int i = 0; i < R; ++i) {
446  sum += m1[i][0] * m2[i][0];
447  }
448  return sum;
449 }
450 
457 template <int M, int N, int P, int Q, class T>
459 {
461  if (N != P) {
462  throw std::runtime_error(
463  "Matrices don't have the right dimensions for multiplication");
464  }
465 
466  Matrix<M, Q, T> res;
467 
470  for (int i = 0; i < M; ++i) {
471  for (int j = 0; j < Q; ++j) {
472  res[i][j] = dot(transpose(m1.getRow(i)), m2.getCol(j));
473  }
474  }
475 
476  return res;
477 }
478 
479 } // namespace matrix
480 
481 } // namespace yage
Matrix< M, N, T > operator/(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:263
Matrix< 1, Cols, Type > getRow(int row) const
Return the row specified row as a Matrix with only one row.
Definition: matrix.h:100
Type & z
Definition: matrix.h:378
Definition: matrix.h:46
Matrix< M, N, T > operator*(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:245
int rowSize() const
Returns the row size of the Matrix.
Definition: matrix.h:90
z(this->data_[2])
Definition: matrix.h:367
2D Vector class.
Definition: matrix.h:326
bool operator==(const Matrix< M, N, T > &lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:272
Type & y
Definition: matrix.h:355
std::vector< Type >::iterator end()
Iterator support for the end.
Definition: matrix.h:133
Type & x
Definition: matrix.h:355
Type & operator[](int col)
Definition: matrix.h:305
Type & y
Definition: matrix.h:378
std::vector< Type > data_
Vector containing the data of the matrix.
Definition: matrix.h:82
Matrix< M, Q, T > multiply(const Matrix< M, N, T > &m1, const Matrix< P, Q, T > &m2)
Multiplies two matrices together.
Definition: matrix.h:458
Type & y()
Definition: matrix.h:343
Type & operator[](int col)
Definition: matrix.h:58
Matrix< Rows, 1, Type > getCol(int col) const
Get a specific column in a column vector.
Definition: matrix.h:114
const Type & operator[](int col) const
Definition: matrix.h:64
w(this->data_[3])
Definition: matrix.h:390
const Type & x() const
Definition: matrix.h:341
Type & x
Definition: matrix.h:378
Matrix< N, M, T > transpose(const Matrix< M, N, T > &m)
Transposes a matrix and returns the result.
Definition: matrix.h:426
int colSize() const
Returns the column size of the Matrix.
Definition: matrix.h:93
const Type & operator[](int col) const
Definition: matrix.h:307
Matrix< Rows, Cols, Type > & operator-=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:182
3D Vector class.
Definition: matrix.h:352
Type & x()
Definition: matrix.h:340
details::Row< Rows, Cols, Type > operator[](int row) const
Definition: matrix.h:165
details::Row< Rows, Cols, Type > operator[](int row)
Definition: matrix.h:160
Matrix< M, N, T > operator+(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:195
Definition: matrix.h:291
Matrix< M, N, T > operator-(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:202
virtual std::string toString() const
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:141
Matrix< Rows, Cols, Type > & operator+=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:171
Base Matrix class used by other similar classes.
Definition: matrix.h:25
T dot(const Matrix< R, 1, T > &m1, const Matrix< R, 1, T > &m2)
Returns the dot product between two vectors.
Definition: matrix.h:442
Type & w
Definition: matrix.h:378
const Type & y() const
Definition: matrix.h:344
std::string toString() const override
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:309
4D Vector class
Definition: matrix.h:375
std::vector< Type >::iterator begin()
Iterator support for the start.
Definition: matrix.h:127
Type & z
Definition: matrix.h:355