Coverage Report

Created: 2026-09-14 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.