/src/openbabel/include/openbabel/math/matrix3x3.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | matrix3x3.cpp - Handle 3D Rotation matrix. |
3 | | |
4 | | Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc. |
5 | | Some portions Copyright (C) 2001-2006 by Geoffrey R. Hutchison |
6 | | Some portions Copyright (C) 2006 by Benoit Jacob |
7 | | |
8 | | This file is part of the Open Babel project. |
9 | | For more information, see <http://openbabel.org/> |
10 | | |
11 | | This program is free software; you can redistribute it and/or modify |
12 | | it under the terms of the GNU General Public License as published by |
13 | | the Free Software Foundation version 2 of the License. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, |
16 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | GNU General Public License for more details. |
19 | | ***********************************************************************/ |
20 | | |
21 | | #ifndef OB_MATRIX3x3_H |
22 | | #define OB_MATRIX3x3_H |
23 | | |
24 | | #include <ostream> |
25 | | |
26 | | #include <openbabel/math/vector3.h> // includes rand.h, which includes <math.h> |
27 | | #include <openbabel/oberror.h> |
28 | | |
29 | | #ifndef RAD_TO_DEG |
30 | | #define RAD_TO_DEG (180.0/M_PI) |
31 | | #endif |
32 | | |
33 | | #ifndef DEG_TO_RAD |
34 | | #define DEG_TO_RAD (M_PI/180.0) |
35 | | #endif |
36 | | |
37 | | namespace OpenBabel |
38 | | { |
39 | | // class introduction in matrix3x3.cpp |
40 | | class OBAPI matrix3x3 |
41 | | { |
42 | | //! Elements of the matrix |
43 | | /*! This array holds the matrix. The first index refers to the |
44 | | row, the second the column. */ |
45 | | double ele[3][3]; |
46 | | |
47 | | public: |
48 | | //! Constructs the zero-matrix |
49 | | matrix3x3(void) |
50 | 16.3k | { |
51 | | // Loops are typically unrolled and/or vectorized |
52 | 65.2k | for (unsigned int i = 0; i < 3; ++i) |
53 | 195k | for (unsigned int j = 0; j < 3; ++j) |
54 | 146k | ele[i][j] = 0.0; |
55 | 16.3k | } |
56 | | |
57 | | //! Constructs s times the unit matrix |
58 | | matrix3x3(double s) |
59 | 44 | { |
60 | | // Loops are typically unrolled and/or vectorized |
61 | 176 | for (unsigned int i = 0; i < 3; ++i) |
62 | 528 | for (unsigned int j = 0; j < 3; ++j) |
63 | 396 | ele[i][j] = 0.0; |
64 | | |
65 | 176 | for (unsigned int i = 0; i < 3; ++i) |
66 | 132 | ele[i][i] = s; |
67 | 44 | } |
68 | | |
69 | | //! Constructs a matrix from row vectors |
70 | | matrix3x3(vector3 row1,vector3 row2,vector3 row3) |
71 | 6.98k | { |
72 | 6.98k | ele[0][0] = row1.x(); |
73 | 6.98k | ele[0][1] = row1.y(); |
74 | 6.98k | ele[0][2] = row1.z(); |
75 | 6.98k | ele[1][0] = row2.x(); |
76 | 6.98k | ele[1][1] = row2.y(); |
77 | 6.98k | ele[1][2] = row2.z(); |
78 | 6.98k | ele[2][0] = row3.x(); |
79 | 6.98k | ele[2][1] = row3.y(); |
80 | 6.98k | ele[2][2] = row3.z(); |
81 | 6.98k | } |
82 | | |
83 | | //! \brief Constructs a matrix from a 3x3-array of doubles |
84 | | /*! The first index represents the row, the second index the column */ |
85 | | matrix3x3(double d[3][3]) |
86 | 0 | { |
87 | | // Loops are typically unrolled and/or vectorized |
88 | 0 | for (unsigned int i = 0; i < 3; ++i) |
89 | 0 | for (unsigned int j = 0; j < 3; ++j) |
90 | 0 | ele[i][j] = d[i][j]; |
91 | | |
92 | | // We could also potentially use memcpy here |
93 | 0 | } |
94 | | |
95 | | //! Destructor |
96 | 31.5k | ~matrix3x3() {} |
97 | | |
98 | | //! \brief Access function |
99 | | /*! Writes the matrix into the 1-dimensional array m, row by |
100 | | row. The array must be able to hold 9 doubles, otherwise your |
101 | | program will segfault. */ |
102 | | void GetArray(double *m) |
103 | 0 | { |
104 | 0 | for (unsigned int i = 0; i < 3; ++i) |
105 | 0 | for (unsigned int j = 0; j < 3; ++j) |
106 | 0 | m[3*i+j] = ele[i][j]; |
107 | 0 | } |
108 | | |
109 | | /*! \return a constant reference to an element of the matrix. |
110 | | row and column must be between 0 and 2. No check is done. */ |
111 | | const double & operator() (int row, int column ) const |
112 | 50.5M | { |
113 | 50.5M | return ele[row][column]; |
114 | 50.5M | } |
115 | | |
116 | | /*! \return a non-constant reference to an element of the matrix. |
117 | | row and column must be between 0 and 2. No check is done. */ |
118 | | double & operator() (int row, int column ) |
119 | 31.8k | { |
120 | 31.8k | return ele[row][column]; |
121 | 31.8k | } |
122 | | |
123 | | //! Calculates the inverse of a matrix. |
124 | | matrix3x3 inverse(void) const |
125 | | #ifdef OB_OLD_MATH_CHECKS |
126 | | noexcept(false) |
127 | | #endif |
128 | | ; |
129 | | |
130 | | //! Calculates the transpose of a matrix. |
131 | | matrix3x3 transpose(void) const; |
132 | | |
133 | | //! \return The determinant of the matrix |
134 | | double determinant() const; |
135 | | |
136 | | //! Checks if a matrix is symmetric |
137 | | bool isSymmetric(void) const; |
138 | | |
139 | | //! Checks if a matrix is orthogonal |
140 | | /*! This method checks if a matrix is orthogonal, i.e. |
141 | | if all column vectors are normalized and |
142 | | are mutually orthogonal. A matrix is orthogonal if, |
143 | | and only if the transformation it describes is orthonormal. |
144 | | An orthonormal transformation is a |
145 | | transformation that preserves length and angle. |
146 | | |
147 | | The check is performed using the method isUnitMatrix() to |
148 | | check if |
149 | | \code |
150 | | *this * transpose() |
151 | | \endcode |
152 | | is a unit matrix. The criterion is therefore numerically quite |
153 | | tight. */ |
154 | | bool isOrthogonal(void) const |
155 | 0 | { |
156 | 0 | return (*this * transpose()).isUnitMatrix(); |
157 | 0 | }; |
158 | | |
159 | | //! \return if a matrix is diagonal |
160 | | bool isDiagonal(void) const; |
161 | | |
162 | | //! \return if a matrix is the unit matrix |
163 | | bool isUnitMatrix(void) const; |
164 | | |
165 | | //! Access function |
166 | | /*! \warning row or column are not in the range 0..2, zero is returned |
167 | | *! \deprecated use the constant operator() instead |
168 | | */ |
169 | | OB_DEPRECATED_MSG("use the constant operator() instead") |
170 | | double Get(int row,int column) const |
171 | 0 | { |
172 | 0 | #ifdef OB_OLD_MATH_CHECKS |
173 | 0 | if (row >= 0 && row <= 2 && column >= 0 && column <= 2) |
174 | 0 | return(ele[row][column]); |
175 | 0 | else |
176 | 0 | return 0.0f; |
177 | 0 | #else |
178 | 0 | return(ele[row][column]); |
179 | 0 | #endif |
180 | 0 | } |
181 | | |
182 | | //! Access function |
183 | | /*! \warning if row or column are not in the range 0..2, nothing will happen |
184 | | *! \deprecated use the non-constant operator() instead |
185 | | */ |
186 | | OB_DEPRECATED_MSG("use the non-constant operator() instead") |
187 | | void Set(int row,int column, double v) |
188 | 0 | { |
189 | 0 | #ifdef OB_OLD_MATH_CHECKS |
190 | 0 | if (row >= 0 && row <= 2 && column >= 0 && column <= 2) |
191 | 0 | ele[row][column]= v; |
192 | 0 | #else |
193 | 0 | ele[row][column]= v; |
194 | 0 | #endif |
195 | 0 | } |
196 | | |
197 | | //! Access function |
198 | | /*! \warning If column is not in the range 0..2, the vector |
199 | | remains unchanged and an exception is thrown. */ |
200 | | void SetColumn(int column, const vector3 &v) |
201 | | #ifdef OB_OLD_MATH_CHECKS |
202 | | noexcept(false) |
203 | | #endif |
204 | | ; |
205 | | |
206 | | //! Access function |
207 | | /*! \warning If column is not in the range 0..2, the vector |
208 | | remains unchanged and an exception is thrown. */ |
209 | | void SetRow(int row, const vector3 &v) |
210 | | #ifdef OB_OLD_MATH_CHECKS |
211 | | noexcept(false) |
212 | | #endif |
213 | | ; |
214 | | |
215 | | //! Access function |
216 | | /*! \warning If col is not in the range 0..2, an exception is |
217 | | thrown. */ |
218 | | vector3 GetColumn(unsigned int col) const |
219 | | #ifdef OB_OLD_MATH_CHECKS |
220 | | noexcept(false) |
221 | | #endif |
222 | | ; |
223 | | |
224 | | //! Access function |
225 | | /*! \warning If row is not in the range 0..2, an exception is |
226 | | thrown. */ |
227 | | vector3 GetRow(unsigned int row) const |
228 | | #ifdef OB_OLD_MATH_CHECKS |
229 | | noexcept(false) |
230 | | #endif |
231 | | ; |
232 | | |
233 | | //! Multiplies all entries of the matrix by a scalar c |
234 | | matrix3x3 &operator*=(const double &c) |
235 | 0 | { |
236 | 0 | for( int i = 0; i < 3; i++ ) |
237 | 0 | for( int j = 0; j < 3; j++ ) |
238 | 0 | ele[i][j] *= c; |
239 | 0 | return *this; |
240 | 0 | } |
241 | | |
242 | | //! Divides all entries of the matrix by a scalar c |
243 | | matrix3x3 &operator/=(const double &c) |
244 | 0 | { |
245 | 0 | return( (*this) *= ( 1.0 / c ) ); |
246 | 0 | } |
247 | | |
248 | | //! \brief Calculate a rotation matrix for rotation about the x, y, and z |
249 | | //! axes by the angles specified (in degrees) |
250 | | void SetupRotMat(double x, double y, double z); |
251 | | |
252 | | //! Calculates a matrix that represents reflection on a plane |
253 | | void PlaneReflection(const vector3 &norm); |
254 | | |
255 | | //! \brief Calculates a rotation matrix, rotating around the specified axis by |
256 | | //! the specified angle (in degrees) |
257 | | void RotAboutAxisByAngle(const vector3 &axis, const double angle); |
258 | | |
259 | | //! Calculate an orthogonalisation matrix for a unit cell |
260 | | //! specified by the parameters alpha, beta, gamma, a, b, c |
261 | | //! where alpha, beta, and gamma are the cell angles (in degrees) |
262 | | //! and a, b, and c are the cell vector lengths |
263 | | //! Used by OBUnitCell |
264 | | void FillOrth(double alpha, double beta, double gamma, |
265 | | double a, double b, double c); |
266 | | |
267 | | //! Find the eigenvalues and -vectors of a symmetric matrix |
268 | | matrix3x3 findEigenvectorsIfSymmetric(vector3 &eigenvals) const |
269 | | #ifdef OB_OLD_MATH_CHECKS |
270 | | noexcept(false) |
271 | | #endif |
272 | | ; |
273 | | |
274 | | //! Matrix-vector multiplication |
275 | | friend OBAPI vector3 operator *(const matrix3x3 &,const vector3 &); |
276 | | |
277 | | //! Matrix-matrix multiplication |
278 | | friend OBAPI matrix3x3 operator *(const matrix3x3 &,const matrix3x3 &); |
279 | | |
280 | | //! Output a text representation of a matrix |
281 | | friend OBAPI std::ostream& operator<< ( std::ostream&, const matrix3x3 & ) ; |
282 | | |
283 | | //! Eigenvalue calculation |
284 | | static void jacobi(unsigned int n, double *a, double *d, double *v); |
285 | | }; |
286 | | |
287 | | #ifndef SWIG |
288 | | OBAPI vector3 center_coords(double*,int); |
289 | | #endif |
290 | | } |
291 | | |
292 | | #endif // OB_MATRIX3x3_H |
293 | | |
294 | | //! \file matrix3x3.h |
295 | | //! \brief Handle 3D Rotation matrix. |