Matrix3x3.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2017 Imperial College London
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef MIRTK_Matrix3x3_H
20 #define MIRTK_Matrix3x3_H
21 
22 #include "mirtk/NumericsExport.h"
23 
24 #include "mirtk/Vector3.h"
25 #include "mirtk/Math.h"
26 
27 
28 namespace mirtk {
29 
30 
31 // NOTE. The (x,y,z) coordinate system is assumed to be right-handed.
32 // Coordinate axis rotation matrices are of the form
33 // RX = 1 0 0
34 // 0 cos(t) -sin(t)
35 // 0 sin(t) cos(t)
36 // where t > 0 indicates a counterclockwise rotation in the yz-plane
37 // RY = cos(t) 0 sin(t)
38 // 0 1 0
39 // -sin(t) 0 cos(t)
40 // where t > 0 indicates a counterclockwise rotation in the zx-plane
41 // RZ = cos(t) -sin(t) 0
42 // sin(t) cos(t) 0
43 // 0 0 1
44 // where t > 0 indicates a counterclockwise rotation in the xy-plane.
45 
46 class Matrix3x3
47 {
48 public:
49  // construction
50  Matrix3x3 ();
51  Matrix3x3 (int);
52  Matrix3x3 (double);
53  Matrix3x3 (const double aafEntry[3][3]);
54  Matrix3x3 (const Matrix3x3& rkMatrix);
55  Matrix3x3 (double fEntry00, double fEntry01, double fEntry02,
56  double fEntry10, double fEntry11, double fEntry12,
57  double fEntry20, double fEntry21, double fEntry22);
58 
59  // member access, allows use of construct mat[r][c]
60  double* operator[] (int iRow);
61  const double* operator[] (int iRow) const;
62  operator double* ();
63  Vector3 GetColumn (int iCol) const;
64 
65  // assignment and comparison
66  Matrix3x3& operator= (const Matrix3x3& rkMatrix);
67  Matrix3x3& operator= (double);
68  bool operator== (const Matrix3x3& rkMatrix) const;
69  bool operator!= (const Matrix3x3& rkMatrix) const;
70 
71  // arithmetic operations
72  Matrix3x3 &operator+=(double);
73  Matrix3x3 &operator-=(double);
74  Matrix3x3 &operator*=(double);
75  Matrix3x3 &operator/=(double);
76 
77  Matrix3x3 operator+ (double) const;
78  Matrix3x3 operator- (double) const;
79  Matrix3x3 operator* (double) const;
80  Matrix3x3 operator/ (double) const;
81 
82  Matrix3x3 &operator+=(const Matrix3x3& rkMatrix);
83  Matrix3x3 &operator-=(const Matrix3x3& rkMatrix);
84  Matrix3x3 &operator*=(const Matrix3x3& rkMatrix);
85  Matrix3x3 &operator/=(const Matrix3x3& rkMatrix);
86 
87  Matrix3x3 operator+ (const Matrix3x3& rkMatrix) const;
88  Matrix3x3 operator- (const Matrix3x3& rkMatrix) const;
89  Matrix3x3 operator* (const Matrix3x3& rkMatrix) const;
90  Matrix3x3 operator/ (const Matrix3x3& rkMatrix) const;
91  Matrix3x3 operator- () const;
92 
93  // matrix * vector [3x3 * 3x1 = 3x1]
94  Vector3 operator* (const Vector3& rkVector) const;
95 
96  // vector * matrix [1x3 * 3x3 = 1x3]
97  friend Vector3 operator* (const Vector3& rkVector,
98  const Matrix3x3& rkMatrix);
99 
100  // scalar * matrix
101  friend Matrix3x3 operator* (double fScalar, const Matrix3x3& rkMatrix);
102 
103  // utilities
104  Matrix3x3 Transpose () const;
105  bool Inverse (Matrix3x3& rkInverse, double fTolerance = 1e-06) const;
106  Matrix3x3 Inverse (double fTolerance = 1e-06) const;
107  double Determinant () const;
108  Matrix3x3 Adjoint() const;
109  double Trace() const;
110 
111  // singular value decomposition
112  void SingularValueDecomposition (Matrix3x3& rkL, Vector3& rkS,
113  Matrix3x3& rkR) const;
114  void SingularValueComposition (const Matrix3x3& rkL,
115  const Vector3& rkS, const Matrix3x3& rkR);
116 
117  // Gram-Schmidt orthonormalization (applied to columns of rotation matrix)
118  void Orthonormalize ();
119 
120  // orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12)
121  void QDUDecomposition (Matrix3x3& rkQ, Vector3& rkD,
122  Vector3& rkU) const;
123 
124  // Polar decomposition of a 3x3 matrix
125  //
126  // This finds the closest orthogonal matrix to input A
127  // (in both the Frobenius and L2 norms).
128  //
129  // Algorithm is that from NJ Higham, SIAM J Sci Stat Comput, 7:1160-1174.
130  //
131  // \sa nifti_mat33_polar
132  Matrix3x3 PolarDecomposition() const;
133 
134  // p=1 norm of specified row
135  double RowNorm(int) const;
136 
137  // p=1 norm of specified column
138  double ColNorm(int) const;
139 
140  // Maximum p=1 row norm
141  double MaxRowNorm() const;
142 
143  // Maximum p=1 col norm
144  double MaxColNorm() const;
145 
146  double SpectralNorm () const;
147 
148  // matrix must be orthonormal
149  void ToAxisAngle (Vector3& rkAxis, double& rfRadians) const;
150  void FromAxisAngle (const Vector3& rkAxis, double fRadians);
151 
152  // The matrix must be orthonormal. The decomposition is yaw*pitch*roll
153  // where yaw is rotation about the Up vector, pitch is rotation about the
154  // Right axis, and roll is rotation about the Direction axis.
155  bool ToEulerAnglesXYZ (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
156  bool ToEulerAnglesXZY (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
157  bool ToEulerAnglesYXZ (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
158  bool ToEulerAnglesYZX (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
159  bool ToEulerAnglesZXY (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
160  bool ToEulerAnglesZYX (double& rfYAngle, double& rfPAngle, double& rfRAngle) const;
161  void FromEulerAnglesXYZ (double fYAngle, double fPAngle, double fRAngle);
162  void FromEulerAnglesXZY (double fYAngle, double fPAngle, double fRAngle);
163  void FromEulerAnglesYXZ (double fYAngle, double fPAngle, double fRAngle);
164  void FromEulerAnglesYZX (double fYAngle, double fPAngle, double fRAngle);
165  void FromEulerAnglesZXY (double fYAngle, double fPAngle, double fRAngle);
166  void FromEulerAnglesZYX (double fYAngle, double fPAngle, double fRAngle);
167 
168  // eigensolver, matrix must be symmetric
169  void EigenSolveSymmetric (double afEigenvalue[3],
170  Vector3 akEigenvector[3]) const;
171 
172  static void TensorProduct (const Vector3& rkU, const Vector3& rkV,
173  Matrix3x3& rkProduct);
174 
175  MIRTK_Numerics_EXPORT static const double EPSILON;
176  MIRTK_Numerics_EXPORT static const Matrix3x3 ZERO;
177  MIRTK_Numerics_EXPORT static const Matrix3x3 IDENTITY;
178 
179  // support for eigensolver
180  void Tridiagonal(double afDiag[3], double afSubDiag[3]);
181  bool QLAlgorithm(double afDiag[3], double afSubDiag[3]);
182 
183  // support for singular value decomposition
184  MIRTK_Numerics_EXPORT static const double ms_fSvdEpsilon;
185  MIRTK_Numerics_EXPORT static const int ms_iSvdMaxIterations;
186  static void Bidiagonalize (Matrix3x3& kA, Matrix3x3& kL,
187  Matrix3x3& kR);
188  static void GolubKahanStep (Matrix3x3& kA, Matrix3x3& kL,
189  Matrix3x3& kR);
190 
191  // support for spectral norm
192  static double MaxCubicRoot (double afCoeff[3]);
193 
194 protected:
195 
196  double m_aafEntry[3][3];
197 };
198 
199 //////////////////////////////////////////////////////////////////////////////
200 // Inline definitions
201 //////////////////////////////////////////////////////////////////////////////
202 
203 //----------------------------------------------------------------------------
204 inline double Matrix3x3::RowNorm(int r) const
205 {
206  return abs(m_aafEntry[r][0]) + abs(m_aafEntry[r][1]) + abs(m_aafEntry[r][2]);
207 }
208 
209 //----------------------------------------------------------------------------
210 inline double Matrix3x3::MaxRowNorm() const
211 {
212  return max(max(RowNorm(0), RowNorm(1)), RowNorm(2));
213 }
214 
215 //----------------------------------------------------------------------------
216 inline double Matrix3x3::ColNorm(int c) const
217 {
218  return abs(m_aafEntry[0][c]) + abs(m_aafEntry[1][c]) + abs(m_aafEntry[2][c]);
219 }
220 
221 //----------------------------------------------------------------------------
222 inline double Matrix3x3::MaxColNorm() const
223 {
224  return max(max(ColNorm(0), ColNorm(1)), ColNorm(2));
225 }
226 
227 
228 } // namespace mirtk
229 
230 #endif // MIRTK_Matrix3x3_H
Definition: IOConfig.h:41
MIRTKCU_API bool operator==(const float1 &a, const float1 &b)
Check two 1D vectors for equality.
Definition: Math.h:731