Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matrix.h
Go to the documentation of this file.
1 
18 #ifndef ION_MATH_MATRIX_H_
19 #define ION_MATH_MATRIX_H_
20 
21 #include <cstring> // For memcpy().
22 #include <istream> // NOLINT
23 #include <ostream> // NOLINT
24 
25 #include "ion/base/logging.h"
26 #include "ion/base/static_assert.h"
27 #include "ion/base/stringutils.h"
28 
29 namespace ion {
30 namespace math {
31 
34 template <int Dimension, typename T>
35 class Matrix {
36  public:
38  enum { kDimension = Dimension };
39  typedef T ValueType;
40 
42  Matrix() : elem_() {}
43 
45  Matrix(T m00, T m01, T m10, T m11); // Only when Dimension == 2.
46  Matrix(T m00, T m01, T m02, // Only when Dimension == 3.
47  T m10, T m11, T m12,
48  T m20, T m21, T m22);
49  Matrix(T m00, T m01, T m02, T m03, // Only when Dimension == 4.
50  T m10, T m11, T m12, T m13,
51  T m20, T m21, T m22, T m23,
52  T m30, T m31, T m32, T m33);
53 
55  explicit Matrix(const T array[Dimension * Dimension]);
56 
59  template <typename U> explicit Matrix(const Matrix<Dimension, U>& other);
60 
62  static Matrix Zero();
63 
65  static Matrix Identity();
66 
68  T& operator()(int row, int col) {
69  CheckIndices(row, col);
70  return elem_[row][col];
71  }
72  T* operator[](int row) {
73  CheckIndices(row, 0);
74  return elem_[row];
75  }
76 
78  const T& operator()(int row, int col) const {
79  CheckIndices(row, col);
80  return elem_[row][col];
81  }
82  const T* operator[](int row) const {
83  CheckIndices(row, 0);
84  return elem_[row];
85  }
86 
88  T* Data() { return &elem_[0][0]; }
89  const T* Data() const { return &elem_[0][0]; }
90 
92  void operator*=(T s) { MultiplyScalar(s); }
93  void operator*=(const Matrix& m) { *this = Product(*this, m); }
94 
96  Matrix operator-() const { return Negation(); }
97 
99  friend Matrix operator*(const Matrix& m, T s) { return Scale(m, s); }
100  friend Matrix operator*(T s, const Matrix& m) { return Scale(m, s); }
101 
103  friend Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
104  return Addition(lhs, rhs);
105  }
106 
108  friend Matrix operator-(const Matrix& lhs, const Matrix& rhs) {
109  return Subtraction(lhs, rhs);
110  }
111 
113  friend Matrix operator*(const Matrix& m0, const Matrix& m1) {
114  return Product(m0, m1);
115  }
116 
118  friend bool operator==(const Matrix& m0, const Matrix& m1) {
119  return AreEqual(m0, m1);
120  }
121  friend bool operator!=(const Matrix& m0, const Matrix& m1) {
122  return !AreEqual(m0, m1);
123  }
124 
125  private:
127  void CheckIndices(int row, int col) const {
132  DCHECK(row >= 0 && row < Dimension && col >= 0 && col < Dimension);
133  }
134 
136  void MultiplyScalar(T s);
137  Matrix Negation() const;
138  static Matrix Addition(const Matrix& lhs, const Matrix& rhs);
139  static Matrix Subtraction(const Matrix& lhs, const Matrix& rhs);
140  static Matrix Scale(const Matrix& m, T s);
141  static Matrix Product(const Matrix& m0, const Matrix& m1);
142  static bool AreEqual(const Matrix& m0, const Matrix& m1);
143 
144  T elem_[Dimension][Dimension];
145 };
146 
148 template <int Dimension, typename T>
149 std::ostream& operator<<(std::ostream& out, const Matrix<Dimension, T>& m) {
150  out << "M[";
151  for (int row = 0; row < Dimension; ++row) {
152  for (int col = 0; col < Dimension; ++col) {
153  out << m(row, col);
154  if (col != Dimension - 1)
155  out << ", ";
156  }
157  if (row < Dimension - 1)
158  out << " ; ";
159  }
160  return out << "]";
161 }
162 
164 template <int Dimension, typename T>
165 std::istream& operator>>(std::istream& in, Matrix<Dimension, T>& m) {
167  if (base::GetExpectedString(in, "M[")) {
168  for (int row = 0; row < Dimension; ++row) {
169  for (int col = 0; col < Dimension; ++col) {
170  in >> mm[row][col];
171  if (col != Dimension - 1 && !base::GetExpectedChar<','>(in))
172  return in;
173  }
174  if (row != Dimension - 1 && !base::GetExpectedChar<';'>(in))
175  return in;
176  }
177  if (base::GetExpectedChar<']'>(in))
178  m = mm;
179  }
180  return in;
181 }
182 
184 
187 
188 
189 template <int Dimension, typename T>
190 Matrix<Dimension, T>::Matrix(T m00, T m01, T m10, T m11) {
191  ION_STATIC_ASSERT(Dimension == 2, "Bad Dimension in Matrix constructor");
192  elem_[0][0] = m00;
193  elem_[0][1] = m01;
194  elem_[1][0] = m10;
195  elem_[1][1] = m11;
196 }
197 
198 template <int Dimension, typename T>
200  T m10, T m11, T m12,
201  T m20, T m21, T m22) {
202  ION_STATIC_ASSERT(Dimension == 3, "Bad Dimension in Matrix constructor");
203  elem_[0][0] = m00;
204  elem_[0][1] = m01;
205  elem_[0][2] = m02;
206  elem_[1][0] = m10;
207  elem_[1][1] = m11;
208  elem_[1][2] = m12;
209  elem_[2][0] = m20;
210  elem_[2][1] = m21;
211  elem_[2][2] = m22;
212 }
213 
214 template <int Dimension, typename T>
215 Matrix<Dimension, T>::Matrix(T m00, T m01, T m02, T m03,
216  T m10, T m11, T m12, T m13,
217  T m20, T m21, T m22, T m23,
218  T m30, T m31, T m32, T m33) {
219  ION_STATIC_ASSERT(Dimension == 4, "Bad Dimension in Matrix constructor");
220  elem_[0][0] = m00;
221  elem_[0][1] = m01;
222  elem_[0][2] = m02;
223  elem_[0][3] = m03;
224  elem_[1][0] = m10;
225  elem_[1][1] = m11;
226  elem_[1][2] = m12;
227  elem_[1][3] = m13;
228  elem_[2][0] = m20;
229  elem_[2][1] = m21;
230  elem_[2][2] = m22;
231  elem_[2][3] = m23;
232  elem_[3][0] = m30;
233  elem_[3][1] = m31;
234  elem_[3][2] = m32;
235  elem_[3][3] = m33;
236 }
237 
238 template <int Dimension, typename T>
239 Matrix<Dimension, T>::Matrix(const T array[Dimension * Dimension]) {
240 #if defined(ION_PLATFORM_WINDOWS) && defined(ION_ARCH_X86_64)
241  if ((reinterpret_cast<size_t>(&array[0]) & 0xF) != 0) {
246  for (int i = 0; i < Dimension; ++i) {
247  for (int j = 0; j < Dimension; ++j) {
248  elem_[i][j] = array[i*Dimension+j];
249  }
250  }
251  return;
252  }
253 #endif
254  memcpy(elem_, array, sizeof(elem_));
255 }
256 
257 template <int Dimension, typename T> template <typename U>
259  for (int i = 0; i < Dimension; ++i) {
260  for (int j = 0; j < Dimension; ++j)
261  elem_[i][j] = static_cast<const T>(other(i, j));
262  }
263 }
264 
265 template <int Dimension, typename T>
267  Matrix result;
268  for (int row = 0; row < Dimension; ++row) {
269  for (int col = 0; col < Dimension; ++col)
270  result.elem_[row][col] = static_cast<T>(0);
271  }
272  return result;
273 }
274 
275 template <int Dimension, typename T>
277  Matrix result;
278  for (int row = 0; row < Dimension; ++row) {
279  for (int col = 0; col < Dimension; ++col) {
280  result.elem_[row][col] =
281  row == col ? static_cast<T>(1) : static_cast<T>(0);
282  }
283  }
284  return result;
285 }
286 
287 template <int Dimension, typename T>
289  for (int row = 0; row < Dimension; ++row) {
290  for (int col = 0; col < Dimension; ++col)
291  elem_[row][col] *= s;
292  }
293 }
294 
295 template <int Dimension, typename T>
296 Matrix<Dimension, T> Matrix<Dimension, T>::Negation() const {
297  Matrix result;
298  for (int row = 0; row < Dimension; ++row) {
299  for (int col = 0; col < Dimension; ++col)
300  result.elem_[row][col] = -elem_[row][col];
301  }
302  return result;
303 }
304 
305 template <int Dimension, typename T>
306 Matrix<Dimension, T> Matrix<Dimension, T>::Scale(const Matrix& m, T s) {
307  Matrix result;
308  for (int row = 0; row < Dimension; ++row) {
309  for (int col = 0; col < Dimension; ++col)
310  result.elem_[row][col] = m.elem_[row][col] * s;
311  }
312  return result;
313 }
314 
315 template<int Dimension, typename T>
316 Matrix<Dimension, T> Matrix<Dimension, T>::Addition(
317  const Matrix<Dimension, T> &lhs, const Matrix<Dimension, T> &rhs) {
318  Matrix<Dimension, T> result;
319  for (int row = 0; row < Dimension; ++row) {
320  for (int col = 0; col < Dimension; ++col)
321  result.elem_[row][col] = lhs.elem_[row][col] + rhs.elem_[row][col];
322  }
323  return result;
324 }
325 
326 template<int Dimension, typename T>
327 Matrix<Dimension, T> Matrix<Dimension, T>::Subtraction(
328  const Matrix<Dimension, T> &lhs, const Matrix<Dimension, T> &rhs) {
329  Matrix<Dimension, T> result;
330  for (int row = 0; row < Dimension; ++row) {
331  for (int col = 0; col < Dimension; ++col)
332  result.elem_[row][col] = lhs.elem_[row][col] - rhs.elem_[row][col];
333  }
334  return result;
335 }
336 
337 template <int Dimension, typename T>
338 Matrix<Dimension, T> Matrix<Dimension, T>::Product(const Matrix& m0,
339  const Matrix& m1) {
340  Matrix result = Matrix::Zero();
341  for (int row = 0; row < Dimension; ++row) {
342  for (int col = 0; col < Dimension; ++col) {
343  for (int i = 0; i < Dimension; ++i)
344  result.elem_[row][col] += m0.elem_[row][i] * m1.elem_[i][col];
345  }
346  }
347  return result;
348 }
349 
350 template <int Dimension, typename T>
351 bool Matrix<Dimension, T>::AreEqual(const Matrix& m0, const Matrix& m1) {
352  for (int row = 0; row < Dimension; ++row) {
353  for (int col = 0; col < Dimension; ++col) {
354  if (m0.elem_[row][col] != m1.elem_[row][col])
355  return false;
356  }
357  }
358  return true;
359 }
360 
362 
365 
366 
373 
374 } // namespace math
375 } // namespace ion
376 
377 #endif // ION_MATH_MATRIX_H_
friend bool operator!=(const Matrix &m0, const Matrix &m1)
Definition: matrix.h:121
T * operator[](int row)
Definition: matrix.h:72
Matrix< 4, float > Matrix4f
Definition: matrix.h:371
void operator*=(T s)
Self-modifying multiplication operators.
Definition: matrix.h:92
void operator*=(const Matrix &m)
Definition: matrix.h:93
Matrix< 2, double > Matrix2d
Definition: matrix.h:368
#define DCHECK(expr)
Definition: logging.h:331
T & operator()(int row, int col)
Mutable element accessors.
Definition: matrix.h:68
Matrix< 3, float > Matrix3f
Definition: matrix.h:369
Matrix operator-() const
Unary operators.
Definition: matrix.h:96
static Matrix Identity()
Returns an identity Matrix.
Definition: matrix.h:276
Matrix< 4, double > Matrix4d
Definition: matrix.h:372
The Matrix class defines a square N-dimensional matrix.
Definition: matrix.h:35
friend Matrix operator*(const Matrix &m0, const Matrix &m1)
Binary multiplication operator.
Definition: matrix.h:113
const T * operator[](int row) const
Definition: matrix.h:82
std::istream & GetExpectedChar(std::istream &in)
Reads a single character from the stream and returns the stream.
Definition: stringutils.h:215
Copyright 2016 Google Inc.
friend Matrix operator*(const Matrix &m, T s)
Binary scale operators.
Definition: matrix.h:99
Matrix< 2, float > Matrix2f
Dimension- and type-specific typedefs.
Definition: matrix.h:367
std::istream & GetExpectedString(std::istream &in, const std::string &expected)
Attempts to read a string from the stream and returns the stream.
Definition: stringutils.h:228
friend bool operator==(const Matrix &m0, const Matrix &m1)
Exact equality and inequality comparisons.
Definition: matrix.h:118
friend Matrix operator*(T s, const Matrix &m)
Definition: matrix.h:100
T * Data()
Return a pointer to the data for interfacing with libraries.
Definition: matrix.h:88
static Matrix Zero()
Returns a Matrix containing all zeroes.
Definition: matrix.h:266
#define ION_STATIC_ASSERT(expr, message)
Copyright 2016 Google Inc.
Definition: static_assert.h:35
std::istream & operator>>(std::istream &in, Angle< T > &a)
Definition: angle.h:135
Matrix()
The default constructor zero-initializes all elements.
Definition: matrix.h:42
friend Matrix operator+(const Matrix &lhs, const Matrix &rhs)
Binary matrix addition.
Definition: matrix.h:103
friend Matrix operator-(const Matrix &lhs, const Matrix &rhs)
Binary matrix subtraction.
Definition: matrix.h:108
const T & operator()(int row, int col) const
Read-only element accessors.
Definition: matrix.h:78
Matrix< 3, double > Matrix3d
Definition: matrix.h:370
const T * Data() const
Definition: matrix.h:89