YAGE  v0.1.1
Yet Another Game Engine
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
matrix.h
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2  * matrix.h
3  *
4  * Copyright (c) 2017 Yann Herklotz Grave <ymherklotz@gmail.com> -- MIT License
5  * See file LICENSE for more details
6  * ----------------------------------------------------------------------------
7  */
8 
12 #ifndef YAGE_MATH_MATRIX_H
13 #define YAGE_MATH_MATRIX_H
14 
15 #include <algorithm>
16 #include <exception>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 #include <vector>
21 
22 namespace yage
23 {
24 
25 template <int Rows, int Cols, class Type>
26 class Matrix;
27 
35 namespace details
36 {
37 
46 template <int Rows, int Cols, class Type>
47 class Row
48 {
49 private:
51  int index_;
52 
53 public:
55  : parent_(parent), index_(index)
56  {
57  }
58 
59  Type &operator[](int col)
60  {
61  // The index is the y-position of the element in the matrix
62  return parent_->data_[index_ * Cols + col];
63  }
64 
65  const Type &operator[](int col) const
66  {
67  return parent_->data_[index_ * Cols + col];
68  }
69 };
70 
71 } // namespace details
72 
75 template <int Rows = 4, int Cols = 4, class Type = double>
76 class Matrix
77 {
78  // friended with the row class so that it can access protected member data.
79  friend class details::Row<Rows, Cols, Type>;
80 
81 protected:
83  std::vector<Type> data_;
84 
85 public:
87  Matrix<Rows, Cols, Type>() : data_(Rows * Cols) {}
88  Matrix<Rows, Cols, Type>(const std::vector<Type> &data) : data_(data) {}
89 
91  int rowSize() const { return Rows; }
92 
94  int colSize() const { return Cols; }
95 
102  {
103  Matrix<1, Cols, Type> rowMatrix;
104  for (int i = 0; i < Cols; ++i) {
105  rowMatrix[0][i] = data_[row][i];
106  }
107  return rowMatrix;
108  }
109 
116  {
117  Matrix<Rows, 1, Type> colMatrix;
118  for (int i = 0; i < Rows; ++i) {
119  colMatrix[i][0] = data_[i][col];
120  }
121  return colMatrix;
122  }
123 
128  typename std::vector<Type>::iterator begin() { return data_.begin(); }
129 
134  typename std::vector<Type>::iterator end() { return data_.end(); }
135 
142  virtual std::string toString() const
143  {
144  std::stringstream ss;
145  ss << '[';
146  for (int i = 0; i < Rows - 1; ++i) {
147  ss << '[';
148  for (int j = 0; j < Cols - 1; ++j) {
149  ss << data_[i * Cols + j] << ' ';
150  }
151  ss << data_[(Rows - 1) * Cols + Cols - 1] << "],";
152  }
153  ss << '[';
154  for (int j = 0; j < Cols - 1; ++j) {
155  ss << data_[(Rows - 1) * Cols + j] << ' ';
156  }
157  ss << data_[(Rows - 1) * Cols + Cols - 1] << "]]";
158  return ss.str();
159  }
160 
162  {
163  return details::Row<Rows, Cols, Type>(this, row);
164  }
165 
167  {
169  row);
170  }
171 
173  {
174  std::vector<Type> out;
175  out.reserve(data_.size());
176  std::transform(data_.begin(), data_.end(), rhs.data_.begin(),
177  std::back_inserter(out),
178  [](Type a, Type b) { return a + b; });
179  data_ = std::move(out);
180  return *this;
181  }
182 
184  {
185  std::vector<Type> out;
186  out.reserve(data_.size());
187  std::transform(data_.begin(), data_.end(), rhs.begin(),
188  std::back_inserter(out),
189  [](Type a, Type b) { return a - b; });
190  data_ = std::move(out);
191  return *this;
192  }
193 };
194 
195 template <int M, int N, class T>
197 {
198  lhs += rhs;
199  return lhs;
200 }
201 
202 template <int M, int N, class T>
204 {
205  lhs -= rhs;
206  return lhs;
207 }
208 
209 template <int M, int N, class T>
211 {
212  for (auto &data : lhs) {
213  data += rhs;
214  }
215  return lhs;
216 }
217 
218 template <int M, int N, class T>
220 {
221  for (auto &data : rhs) {
222  data += lhs;
223  }
224  return rhs;
225 }
226 
227 template <int M, int N, class T>
229 {
230  for (auto &data : lhs) {
231  data -= rhs;
232  }
233  return lhs;
234 }
235 
236 template <int M, int N, class T>
238 {
239  for (auto &data : rhs) {
240  data = lhs - data;
241  }
242  return rhs;
243 }
244 
245 template <int M, int N, class T>
247 {
248  for (auto &data : lhs) {
249  data *= rhs;
250  }
251  return lhs;
252 }
253 
254 template <int M, int N, class T>
256 {
257  for (auto &data : rhs) {
258  data *= lhs;
259  }
260  return rhs;
261 }
262 
263 template <int M, int N, class T>
265 {
266  for (auto &data : lhs) {
267  data /= rhs;
268  }
269  return lhs;
270 }
271 
272 template <int M, int N, class T>
273 bool operator==(const Matrix<M, N, T> &lhs, const Matrix<M, N, T> &rhs)
274 {
275  for (int i = 0; i < M; ++i) {
276  for (int j = 0; j < N; ++j) {
277  if (lhs[i][j] != rhs[i][j]) {
278  return false;
279  }
280  }
281  }
282  return true;
283 }
284 
285 template <int M, int N, class T>
286 std::ostream &operator<<(std::ostream &os, const Matrix<M, N, T> &mat)
287 {
288  return os << mat.toString();
289 }
290 
291 template <int Rows = 2, class Type = double>
292 class Vector : public Matrix<Rows, 1, Type>
293 {
294 public:
297  : Matrix<Rows, 1, Type>(other)
298  {
299  }
300 
301  Vector<Rows, Type>(const std::vector<Type> &data)
302  : Matrix<Rows, 1, Type>(data)
303  {
304  }
305 
306  Type &operator[](int col) { return this->data_[col]; }
307 
308  const Type &operator[](int col) const { return this->data_[col]; }
309 
310  std::string toString() const override
311  {
312  std::stringstream ss;
313  ss << "[";
314  for (std::size_t i = 0; i < this->data_.size() - 1; ++i) {
315  ss << this->data_[i] << " ";
316  }
317  ss << this->data_[this->data_.size() - 1] << "]";
318  return ss.str();
319  }
320 };
321 
326 template <class Type = double>
327 class Vector2 : public Vector<2, Type>
328 {
329 public:
331  Vector2<Type>(const std::vector<Type> &data) : Vector<2, Type>(data) {}
332 
333  Vector2<Type>(Type x, Type y)
334  {
335  this->data_[0] = x;
336  this->data_[1] = y;
337  }
338 
340 
341  Type &x() { return this->data_[0]; }
342 
343  const Type &x() const { return this->data_[0]; }
344 
345  Type &y() { return this->data_[1]; }
346 
347  const Type &y() const { return this->data_[1]; }
348 };
349 
353 
359 namespace matrix
360 {
361 
366 template <int M, int N, class T>
368 {
369  Matrix<N, M, T> trans;
370  for (int i = 0; i < M; ++i) {
371  for (int j = 0; j < N; ++j) {
372  trans[j][i] = m[i][j];
373  }
374  }
375  return trans;
376 }
377 
382 template <int R, class T>
383 T dot(const Matrix<R, 1, T> &m1, const Matrix<R, 1, T> &m2)
384 {
385  T sum = 0;
386  for (int i = 0; i < R; ++i) {
387  sum += m1[i][0] * m2[i][0];
388  }
389  return sum;
390 }
391 
398 template <int M, int N, int P, int Q, class T>
400 {
402  if (N != P) {
403  throw std::runtime_error(
404  "Matrices don't have the right dimensions for multiplication");
405  }
406 
407  Matrix<M, Q, T> res;
408 
411  for (int i = 0; i < M; ++i) {
412  for (int j = 0; j < Q; ++j) {
413  res[i][j] = dot(transpose(m1.getRow(i)), m2.getCol(j));
414  }
415  }
416 
417  return res;
418 }
419 
420 } // namespace matrix
421 
422 } // namespace yage
423 
424 #endif
Matrix< M, N, T > operator/(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:264
Matrix< 1, Cols, Type > getRow(int row) const
Return the row specified row as a Matrix with only one row.
Definition: matrix.h:101
Definition: matrix.h:47
Matrix< M, N, T > operator*(Matrix< M, N, T > lhs, const T &rhs)
Definition: matrix.h:246
int rowSize() const
Returns the row size of the Matrix.
Definition: matrix.h:91
2D Vector class.
Definition: matrix.h:327
bool operator==(const Matrix< M, N, T > &lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:273
std::vector< Type >::iterator end()
Iterator support for the end.
Definition: matrix.h:134
int index_
Definition: matrix.h:51
Type & operator[](int col)
Definition: matrix.h:306
std::vector< Type > data_
Vector containing the data of the matrix.
Definition: matrix.h:83
Matrix< M, Q, T > multiply(const Matrix< M, N, T > &m1, const Matrix< P, Q, T > &m2)
Multiplies two matrices together.
Definition: matrix.h:399
Type & y()
Definition: matrix.h:345
Type & operator[](int col)
Definition: matrix.h:59
Matrix< Rows, Cols, Type > * parent_
Definition: matrix.h:50
Matrix< Rows, 1, Type > getCol(int col) const
Get a specific column in a column vector.
Definition: matrix.h:115
const Type & operator[](int col) const
Definition: matrix.h:65
const Type & x() const
Definition: matrix.h:343
Matrix< N, M, T > transpose(const Matrix< M, N, T > &m)
Transposes a matrix and returns the result.
Definition: matrix.h:367
int colSize() const
Returns the column size of the Matrix.
Definition: matrix.h:94
const Type & operator[](int col) const
Definition: matrix.h:308
Matrix< Rows, Cols, Type > & operator-=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:183
Type & x()
Definition: matrix.h:341
details::Row< Rows, Cols, Type > operator[](int row) const
Definition: matrix.h:166
details::Row< Rows, Cols, Type > operator[](int row)
Definition: matrix.h:161
Matrix< M, N, T > operator+(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:196
Definition: matrix.h:292
Matrix< M, N, T > operator-(Matrix< M, N, T > lhs, const Matrix< M, N, T > &rhs)
Definition: matrix.h:203
virtual std::string toString() const
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:142
Matrix< Rows, Cols, Type > & operator+=(const Matrix< Rows, Cols, Type > &rhs)
Definition: matrix.h:172
Base Matrix class used by other similar classes.
Definition: matrix.h:26
T dot(const Matrix< R, 1, T > &m1, const Matrix< R, 1, T > &m2)
Returns the dot product between two vectors.
Definition: matrix.h:383
const Type & y() const
Definition: matrix.h:347
std::string toString() const override
Prints out the matrix, but can also be implemented by other classes to print data differently...
Definition: matrix.h:310
std::vector< Type >::iterator begin()
Iterator support for the start.
Definition: matrix.h:128