Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
matrixutils.cc
Go to the documentation of this file.
1 
18 #include "ion/math/matrixutils.h"
19 
20 #include "ion/base/logging.h"
21 #include "ion/math/utils.h"
22 #include "ion/math/vectorutils.h"
23 
24 namespace ion {
25 namespace math {
26 
27 namespace {
28 
30 
34 
35 
37 static bool IsCofactorNegated(int row, int col) {
39  return ((row + col) & 1) != 0;
40 }
41 
42 template <typename T>
43 static T CofactorElement3(const Matrix<3, T>& m, int row, int col) {
44  static const int index[3][2] = { {1, 2}, {0, 2}, {0, 1} };
45  const int i0 = index[row][0];
46  const int i1 = index[row][1];
47  const int j0 = index[col][0];
48  const int j1 = index[col][1];
49  const T cofactor = m(i0, j0) * m(i1, j1) - m(i0, j1) * m(i1, j0);
50  return IsCofactorNegated(row, col) ? -cofactor : cofactor;
51 }
52 
53 template <typename T>
54 static T CofactorElement4(const Matrix<4, T>& m, int row, int col) {
57  static const int index[4][3] = { {1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2} };
58  const int i0 = index[row][0];
59  const int i1 = index[row][1];
60  const int i2 = index[row][2];
61  const int j0 = index[col][0];
62  const int j1 = index[col][1];
63  const int j2 = index[col][2];
64  const T c0 = m(i0, j0) * (m(i1, j1) * m(i2, j2) - m(i1, j2) * m(i2, j1));
65  const T c1 = -m(i0, j1) * (m(i1, j0) * m(i2, j2) - m(i1, j2) * m(i2, j0));
66  const T c2 = m(i0, j2) * (m(i1, j0) * m(i2, j1) - m(i1, j1) * m(i2, j0));
67  const T cofactor = c0 + c1 + c2;
68  return IsCofactorNegated(row, col) ? -cofactor : cofactor;
69 }
70 
72 
76 
77 
78 template <typename T>
79 static T Determinant2(const Matrix<2, T>& m) {
80  return m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0);
81 }
82 
83 template <typename T>
84 static T Determinant3(const Matrix<3, T>& m) {
85  return (m(0, 0) * CofactorElement3(m, 0, 0) +
86  m(0, 1) * CofactorElement3(m, 0, 1) +
87  m(0, 2) * CofactorElement3(m, 0, 2));
88 }
89 
90 template <typename T>
91 static T Determinant4(const Matrix<4, T>& m) {
92  return (m(0, 0) * CofactorElement4(m, 0, 0) +
93  m(0, 1) * CofactorElement4(m, 0, 1) +
94  m(0, 2) * CofactorElement4(m, 0, 2) +
95  m(0, 3) * CofactorElement4(m, 0, 3));
96 }
97 
99 
103 
104 
105 template <typename T>
106 Matrix<2, T> CofactorMatrix2(const Matrix<2, T>& m) {
107  return Matrix<2, T>(m(1, 1), -m(1, 0),
108  -m(0, 1), m(0, 0));
109 }
110 
111 template <typename T>
112 Matrix<3, T> CofactorMatrix3(const Matrix<3, T>& m) {
113  Matrix<3, T> result;
114  for (int row = 0; row < 3; ++row) {
115  for (int col = 0; col < 3; ++col)
116  result(row, col) = CofactorElement3(m, row, col);
117  }
118  return result;
119 }
120 
121 template <typename T>
122 Matrix<4, T> CofactorMatrix4(const Matrix<4, T>& m) {
123  Matrix<4, T> result;
124  for (int row = 0; row < 4; ++row) {
125  for (int col = 0; col < 4; ++col)
126  result(row, col) = CofactorElement4(m, row, col);
127  }
128  return result;
129 }
130 
132 
136 
137 
138 template <typename T>
139 Matrix<2, T> Adjugate2(const Matrix<2, T>& m, T* determinant) {
140  const T m00 = m(0, 0);
141  const T m01 = m(0, 1);
142  const T m10 = m(1, 0);
143  const T m11 = m(1, 1);
144  if (determinant)
145  *determinant = m00 * m11 - m01 * m10;
146  return Matrix<2, T>(m11, -m01, -m10, m00);
147 }
148 
149 template <typename T>
150 Matrix<3, T> Adjugate3(const Matrix<3, T>& m, T* determinant) {
151  const Matrix<3, T> cofactor_matrix = CofactorMatrix3(m);
152  if (determinant) {
153  *determinant = m(0, 0) * cofactor_matrix(0, 0) +
154  m(0, 1) * cofactor_matrix(0, 1) +
155  m(0, 2) * cofactor_matrix(0, 2);
156  }
157  return Transpose(cofactor_matrix);
158 }
159 
160 template <typename T>
161 Matrix<4, T> Adjugate4(const Matrix<4, T>& m, T* determinant) {
169  const T s0 = m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1);
170  const T s1 = m(0, 0) * m(1, 2) - m(1, 0) * m(0, 2);
171  const T s2 = m(0, 0) * m(1, 3) - m(1, 0) * m(0, 3);
172 
173  const T s3 = m(0, 1) * m(1, 2) - m(1, 1) * m(0, 2);
174  const T s4 = m(0, 1) * m(1, 3) - m(1, 1) * m(0, 3);
175  const T s5 = m(0, 2) * m(1, 3) - m(1, 2) * m(0, 3);
176 
177  const T c0 = m(2, 0) * m(3, 1) - m(3, 0) * m(2, 1);
178  const T c1 = m(2, 0) * m(3, 2) - m(3, 0) * m(2, 2);
179  const T c2 = m(2, 0) * m(3, 3) - m(3, 0) * m(2, 3);
180 
181  const T c3 = m(2, 1) * m(3, 2) - m(3, 1) * m(2, 2);
182  const T c4 = m(2, 1) * m(3, 3) - m(3, 1) * m(2, 3);
183  const T c5 = m(2, 2) * m(3, 3) - m(3, 2) * m(2, 3);
184 
185  if (determinant)
186  *determinant = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0;
187 
188  return Matrix<4, T>(
189  m(1, 1) * c5 - m(1, 2) * c4 + m(1, 3) * c3,
190  -m(0, 1) * c5 + m(0, 2) * c4 - m(0, 3) * c3,
191  m(3, 1) * s5 - m(3, 2) * s4 + m(3, 3) * s3,
192  -m(2, 1) * s5 + m(2, 2) * s4 - m(2, 3) * s3,
193 
194  -m(1, 0) * c5 + m(1, 2) * c2 - m(1, 3) * c1,
195  m(0, 0) * c5 - m(0, 2) * c2 + m(0, 3) * c1,
196  -m(3, 0) * s5 + m(3, 2) * s2 - m(3, 3) * s1,
197  m(2, 0) * s5 - m(2, 2) * s2 + m(2, 3) * s1,
198 
199  m(1, 0) * c4 - m(1, 1) * c2 + m(1, 3) * c0,
200  -m(0, 0) * c4 + m(0, 1) * c2 - m(0, 3) * c0,
201  m(3, 0) * s4 - m(3, 1) * s2 + m(3, 3) * s0,
202  -m(2, 0) * s4 + m(2, 1) * s2 - m(2, 3) * s0,
203 
204  -m(1, 0) * c3 + m(1, 1) * c1 - m(1, 2) * c0,
205  m(0, 0) * c3 - m(0, 1) * c1 + m(0, 2) * c0,
206  -m(3, 0) * s3 + m(3, 1) * s1 - m(3, 2) * s0,
207  m(2, 0) * s3 - m(2, 1) * s1 + m(2, 2) * s0);
208 }
209 
210 } // anonymous namespace
211 
213 
220 
221 
225 
226 template <int Dimension, typename T>
228  DCHECK(false) << "Unspecialized Matrix Determinant function used.";
229 }
230 
231 template <int Dimension, typename T>
233  DCHECK(false) << "Unspecialized Matrix Cofactor function used.";
234 }
235 
236 template <int Dimension, typename T>
238  const Matrix<Dimension, T>& m, T* determinant) {
239  DCHECK(false) << "Unspecialized Matrix Adjugate function used.";
240 }
241 
242 template <int Dimension, typename T>
244  const Matrix<Dimension, T>& m, T* determinant) {
246  T det;
247  Matrix<Dimension, T> adjugate = AdjugateWithDeterminant(m, &det);
248  if (determinant)
249  *determinant = det;
250  if (det == static_cast<T>(0))
252  else
253  return adjugate * (static_cast<T>(1) / det);
254 }
255 
256 template <int Dimension, typename T>
257 bool MatrixAlmostOrthogonal(const Matrix<Dimension, T>& m, T tolerance) {
258  for (int col1 = 0; col1 < Dimension; ++col1) {
259  Vector<Dimension, T> column = Column(m, col1);
261  for (int col2 = col1 + 1; col2 < Dimension; ++col2)
262  if (Dot(column, Column(m, col2)) > tolerance)
263  return false;
265  if (Abs(LengthSquared(column) - static_cast<T>(1)) > tolerance)
266  return false;
267  }
268  return true;
269 }
270 
274 
275 #define ION_SPECIALIZE_MATRIX_FUNCS(dim, scalar) \
276 template <> scalar ION_API Determinant(const Matrix<dim, scalar>& m) { \
277  return Determinant ## dim(m); \
278 } \
279 template <> Matrix<dim, scalar> ION_API CofactorMatrix( \
280  const Matrix<dim, scalar>& m) { \
281  return CofactorMatrix ## dim(m); \
282 } \
283 template <> Matrix<dim, scalar> ION_API AdjugateWithDeterminant( \
284  const Matrix<dim, scalar>& m, scalar* determinant) { \
285  return Adjugate ## dim(m, determinant); \
286 } \
287  \
288 /* Explicit instantiations. */ \
289 template Matrix<dim, scalar> ION_API InverseWithDeterminant( \
290  const Matrix<dim, scalar>& m, scalar* determinant); \
291 template bool ION_API MatrixAlmostOrthogonal( \
292  const Matrix<dim, scalar>& m, scalar tolerance)
293 
295 ION_SPECIALIZE_MATRIX_FUNCS(2, double);
297 ION_SPECIALIZE_MATRIX_FUNCS(3, double);
299 ION_SPECIALIZE_MATRIX_FUNCS(4, double);
300 
301 #undef ION_SPECIALIZE_MATRIX_FUNCS
302 
303 } // namespace math
304 } // namespace ion
Matrix< Dimension, T > AdjugateWithDeterminant(const Matrix< Dimension, T > &m, T *determinant)
Returns the adjugate of the matrix, which is defined as the transpose of the cofactor matrix...
Definition: matrixutils.cc:237
#define DCHECK(expr)
Definition: logging.h:331
T Dot(const Vector< Dimension, T > &v0, const Vector< Dimension, T > &v1)
Returns the dot (inner) product of two Vectors.
Definition: vectorutils.h:38
bool MatrixAlmostOrthogonal(const Matrix< Dimension, T > &m, T tolerance)
Returns true if the dot product of all column vector pairs in the matrix is less than a provided tole...
Definition: matrixutils.cc:257
Vector< Dimension, T > Column(const Matrix< Dimension, T > &m, int col)
Returns a particular column of a matrix as a vector.
Definition: matrixutils.h:103
The Matrix class defines a square N-dimensional matrix.
Definition: matrix.h:35
T Determinant(const Matrix< Dimension, T > &m)
Public functions.
Definition: matrixutils.cc:227
Matrix< Dimension, T > CofactorMatrix(const Matrix< Dimension, T > &m)
Returns the signed cofactor matrix (adjunct) of the matrix.
Definition: matrixutils.cc:232
Copyright 2016 Google Inc.
Vector.
Definition: vector.h:180
Matrix< Dimension, T > InverseWithDeterminant(const Matrix< Dimension, T > &m, T *determinant)
Returns the inverse of the matrix.
Definition: matrixutils.cc:243
static Matrix Zero()
Returns a Matrix containing all zeroes.
Definition: matrix.h:266
const T Abs(const T &val)
Returns the absolute value of a number in a type-safe way.
Definition: utils.h:42
Matrix< Dimension, T > Transpose(const Matrix< Dimension, T > &m)
Public functions.
Definition: matrixutils.h:65
ION_SPECIALIZE_MATRIX_FUNCS(2, float)
T LengthSquared(const Vector< Dimension, T > &v)
Returns the square of the length of a Vector.
Definition: vectorutils.h:64