YAGE  0.02
Yet Another Game Engine
matrix.hpp
Go to the documentation of this file.
1 /* ----------------------------------------------------------------------------
2  * matrix.hpp
3  *
4  * Copyright (c) 2017 Yann Herklotz Grave <ymherklotz@gmail.com> -- MIT License
5  * See file LICENSE for more details
6  * ----------------------------------------------------------------------------
7  */
8 
19 #ifndef YAGE_MATH_MATRIX_HPP
20 #define YAGE_MATH_MATRIX_HPP
21 
22 #include <algorithm>
23 #include <exception>
24 #include <iostream>
25 #include <sstream>
26 #include <string>
27 #include <vector>
28 
29 namespace yage {
30 
31 template <int Rows, int Cols, class Type>
32 class Matrix;
33 
41 namespace detail {
42 
51 template <int Rows, int Cols, class Type>
52 class Row {
53 private:
54  Matrix<Rows, Cols, Type>* parent_;
55  int index_;
56 
57 public:
58  Row<Rows, Cols, Type>(Matrix<Rows, Cols, Type>* parent, int index)
59  : parent_(parent), index_(index) {}
60 
61  Type& operator[](int col) {
62  // the index is the y-position of the element in the matrix
63  return parent_->data_[index_ * Cols + col];
64  }
65 
66  const Type& operator[](int col) const {
67  return parent_->data_[index_ * Cols + col];
68  }
69 };
70 
71 } // detail
72 
81 template <int Rows = 4, int Cols = 4, class Type = double>
82 class Matrix {
83  // friended with the row class so that it can access protected member data
84  friend class detail::Row<Rows, Cols, Type>;
85 
86 protected:
88  std::vector<Type> data_;
89 
90 public:
92  Matrix<Rows, Cols, Type>() : data_(Rows * Cols) {}
93  Matrix<Rows, Cols, Type>(const std::vector<Type>& data) : data_(data) {}
94 
96  int rowSize() const { return Rows; }
97 
99  int colSize() const { return Cols; }
100 
107  Matrix<1, Cols, Type> getRow(int row) const {
108  Matrix<1, Cols, Type> rowMatrix;
109  for (int i = 0; i < Cols; ++i) {
110  rowMatrix[0][i] = data_[row][i];
111  }
112  return rowMatrix;
113  }
114 
115  // returns the column in a column matrix
116  Matrix<Rows, 1, Type> getCol(int col) const {
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 
124  // iterator support for begin
125  typename std::vector<Type>::iterator begin() { return data_.begin(); }
126 
127  // iterator support for end
128  typename std::vector<Type>::iterator end() { return data_.end(); }
129 
130  // prints out the matrix, but can also be implemented by other classes to
131  // print data differently
132  virtual std::string toString() const {
133  std::stringstream ss;
134  ss << '[';
135  for (int i = 0; i < Rows - 1; ++i) {
136  ss << '[';
137  for (int j = 0; j < Cols - 1; ++j) {
138  ss << data_[i * Cols + j] << ' ';
139  }
140  ss << data_[(Rows - 1) * Cols + Cols - 1] << "],";
141  }
142  ss << '[';
143  for (int j = 0; j < Cols - 1; ++j) {
144  ss << data_[(Rows - 1) * Cols + j] << ' ';
145  }
146  ss << data_[(Rows - 1) * Cols + Cols - 1] << "]]";
147  return ss.str();
148  }
149 
150  detail::Row<Rows, Cols, Type> operator[](int row) {
151  return detail::Row<Rows, Cols, Type>(this, row);
152  }
153 
154  detail::Row<Rows, Cols, Type> operator[](int row) const {
155  // TODO got to fix this
156  return detail::Row<Rows, Cols, Type>((Matrix<Rows, Cols, Type>*)this,
157  row);
158  }
159 
160  Matrix<Rows, Cols, Type>& operator+=(const Matrix<Rows, Cols, Type>& rhs) {
161  std::vector<Type> out;
162  out.reserve(data_.size());
163  std::transform(data_.begin(), data_.end(), rhs.data_.begin(),
164  std::back_inserter(out),
165  [](Type a, Type b) { return a + b; });
166  data_ = std::move(out);
167  return *this;
168  }
169 
170  Matrix<Rows, Cols, Type>& operator-=(const Matrix<Rows, Cols, Type>& rhs) {
171  std::vector<Type> out;
172  out.reserve(data_.size());
173  std::transform(data_.begin(), data_.end(), rhs.begin(),
174  std::back_inserter(out),
175  [](Type a, Type b) { return a - b; });
176  data_ = std::move(out);
177  return *this;
178  }
179 };
180 
181 template <int M, int N, class T>
182 Matrix<M, N, T> operator+(Matrix<M, N, T> lhs, const Matrix<M, N, T>& rhs) {
183  lhs += rhs;
184  return lhs;
185 }
186 
187 template <int M, int N, class T>
188 Matrix<M, N, T> operator-(Matrix<M, N, T> lhs, const Matrix<M, N, T>& rhs) {
189  lhs -= rhs;
190  return lhs;
191 }
192 
193 template <int M, int N, class T>
194 Matrix<M, N, T> operator+(Matrix<M, N, T> lhs, const T& rhs) {
195  for (auto& data : lhs) {
196  data += rhs;
197  }
198  return lhs;
199 }
200 
201 template <int M, int N, class T>
202 Matrix<M, N, T> operator+(const T& lhs, Matrix<M, N, T> rhs) {
203  for (auto& data : rhs) {
204  data += lhs;
205  }
206  return rhs;
207 }
208 
209 template <int M, int N, class T>
210 Matrix<M, N, T> operator-(Matrix<M, N, T> lhs, const T& rhs) {
211  for (auto& data : lhs) {
212  data -= rhs;
213  }
214  return lhs;
215 }
216 
217 template <int M, int N, class T>
218 Matrix<M, N, T> operator-(const T& lhs, Matrix<M, N, T> rhs) {
219  for (auto& data : rhs) {
220  data = lhs - data;
221  }
222  return rhs;
223 }
224 
225 template <int M, int N, class T>
226 Matrix<M, N, T> operator*(Matrix<M, N, T> lhs, const T& rhs) {
227  for (auto& data : lhs) {
228  data *= rhs;
229  }
230  return lhs;
231 }
232 
233 template <int M, int N, class T>
234 Matrix<M, N, T> operator*(const T& lhs, Matrix<M, N, T> rhs) {
235  for (auto& data : rhs) {
236  data *= lhs;
237  }
238  return rhs;
239 }
240 
241 template <int M, int N, class T>
242 Matrix<M, N, T> operator/(Matrix<M, N, T> lhs, const T& rhs) {
243  for (auto& data : lhs) {
244  data /= rhs;
245  }
246  return lhs;
247 }
248 
249 template <int M, int N, class T>
250 bool operator==(const Matrix<M, N, T>& lhs, const Matrix<M, N, T>& rhs) {
251  for (int i = 0; i < M; ++i)
252  for (int j = 0; j < N; ++j)
253  if (lhs[i][j] != rhs[i][j]) return false;
254  return true;
255 }
256 
257 template <int M, int N, class T>
258 std::ostream& operator<<(std::ostream& os, const Matrix<M, N, T>& mat) {
259  return os << mat.toString();
260 }
261 
262 template <int Rows = 2, class Type = double>
263 class Vector : public Matrix<Rows, 1, Type> {
264 public:
265  Vector<Rows, Type>() : Matrix<Rows, 1, Type>() {}
266  Vector<Rows, Type>(const Matrix<Rows, 1, Type>& other)
267  : Matrix<Rows, 1, Type>(other) {}
268  Vector<Rows, Type>(const std::vector<Type>& data)
269  : Matrix<Rows, 1, Type>(data) {}
270 
271  Type& operator[](int col) { return this->data_[col]; }
272 
273  const Type& operator[](int col) const { return this->data_[col]; }
274 
275  virtual std::string toString() const {
276  std::stringstream ss;
277  ss << "[";
278  for (std::size_t i = 0; i < this->data_.size() - 1; ++i) {
279  ss << this->data_[i] << " ";
280  }
281  ss << this->data_[this->data_.size() - 1] << "]";
282  return ss.str();
283  }
284 };
285 
290 template <class Type = double>
291 class Vector2 : public Vector<2, Type> {
292 public:
293  Vector2<Type>() : Vector<2, Type>() {}
294  Vector2<Type>(const std::vector<Type>& data) : Vector<2, Type>(data) {}
295 
296  Vector2<Type>(Type x, Type y) {
297  this->data_[0] = x;
298  this->data_[1] = y;
299  }
300 
301  Vector2<Type>(const Matrix<2, 1, Type>& other) : Vector<2, Type>(other) {}
302 
303  Type& x() { return this->data_[0]; }
304 
305  const Type& x() const { return this->data_[0]; }
306 
307  Type& y() { return this->data_[1]; }
308 
309  const Type& y() const { return this->data_[1]; }
310 };
311 
314 
316 namespace matrix {
317 
322 template <int M, int N, class T>
324  Matrix<N, M, T> trans;
325  for (int i = 0; i < M; ++i) {
326  for (int j = 0; j < N; ++j) {
327  trans[j][i] = m[i][j];
328  }
329  }
330  return trans;
331 }
332 
337 template <int R, class T>
338 T dot(const Matrix<R, 1, T>& m1, const Matrix<R, 1, T>& m2) {
339  T sum = 0;
340  for (int i = 0; i < R; ++i) {
341  sum += m1[i][0] * m2[i][0];
342  }
343  return sum;
344 }
345 
352 template <int M, int N, int P, int Q, class T>
354  if (N != P) {
355  throw std::runtime_error(
356  "Matrices don't have the right dimensions for multiplication");
357  }
358 
359  Matrix<M, Q, T> res;
360 
361  for (int i = 0; i < M; ++i) {
362  for (int j = 0; j < Q; ++j) {
363  res[i][j] = dot(transpose(m1.getRow(i)), m2.getCol(j));
364  }
365  }
366 
367  return res;
368 }
369 
370 } // matrix
371 
372 } // yage
373 
374 #endif
int rowSize() const
Returns the row size of the Matrix.
Definition: matrix.hpp:96
int colSize() const
Returns the column size of the Matrixxs.
Definition: matrix.hpp:99
2D Vector class.
Definition: matrix.hpp:291
std::vector< Type > data_
Vector containing the data of the matrix.
Definition: matrix.hpp:88
Matrix< M, Q, T > multiply(const Matrix< M, N, T > &m1, const Matrix< P, Q, T > &m2)
Multiplies two matrices together.
Definition: matrix.hpp:353
Matrix< N, M, T > transpose(const Matrix< M, N, T > &m)
Transposes a matrix and returns the result.
Definition: matrix.hpp:323
Base Matrix class used by other similar classes.
Definition: matrix.hpp:32
T dot(const Matrix< R, 1, T > &m1, const Matrix< R, 1, T > &m2)
Returns the dot product between two vectors.
Definition: matrix.hpp:338
Matrix< 1, Cols, Type > getRow(int row) const
Return the row specified row as a Matrix with only one row.
Definition: matrix.hpp:107
Definition: camera2d.hpp:17