/usr/include/libwildmagic/Wm5Matrix3.h is in libwildmagic-dev 5.13-1ubuntu3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | // Geometric Tools, LLC
// Copyright (c) 1998-2014
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
//
// File Version: 5.0.1 (2010/10/01)
#ifndef WM5MATRIX3_H
#define WM5MATRIX3_H
// The (x,y,z) coordinate system is assumed to be right-handed. Coordinate
// axis rotation matrices are of the form
// RX = 1 0 0
// 0 cos(t) -sin(t)
// 0 sin(t) cos(t)
// where t > 0 indicates a counterclockwise rotation in the yz-plane
// RY = cos(t) 0 sin(t)
// 0 1 0
// -sin(t) 0 cos(t)
// where t > 0 indicates a counterclockwise rotation in the zx-plane
// RZ = cos(t) -sin(t) 0
// sin(t) cos(t) 0
// 0 0 1
// where t > 0 indicates a counterclockwise rotation in the xy-plane.
#include "Wm5MathematicsLIB.h"
#include "Wm5Table.h"
#include "Wm5Vector3.h"
#include "Wm5SingularValueDecomposition.h"
namespace Wm5
{
template <typename Real>
class Matrix3 : public Table<3,3,Real>
{
public:
// If makeZero is 'true', create the zero matrix; otherwise, create the
// identity matrix.
Matrix3 (bool makeZero = true);
// Copy constructor.
Matrix3 (const Matrix3& mat);
// Input mrc is in row r, column c.
Matrix3 (Real m00, Real m01, Real m02, Real m10, Real m11, Real m12,
Real m20, Real m21, Real m22);
// Create a matrix from an array of numbers. The input array is
// interpreted based on the bool input as
// true: entry[0..8]={m00,m01,m02,m10,m11,m12,m20,m21,m22} [row major]
// false: entry[0..8]={m00,m10,m20,m01,m11,m21,m02,m12,m22} [col major]
Matrix3 (const Real entry[9], bool rowMajor);
// Create matrices based on vector input. The bool is interpreted as
// true: vectors are columns of the matrix
// false: vectors are rows of the matrix
Matrix3 (const Vector3<Real>& u, const Vector3<Real>& v,
const Vector3<Real>& w, bool columns);
Matrix3 (const Vector3<Real>* v, bool columns);
// Create a diagonal matrix, m01 = m10 = m02 = m20 = m12 = m21 = 0.
Matrix3 (Real m00, Real m11, Real m22);
// Create rotation matrices (positive angle -> counterclockwise). The
// angle must be in radians, not degrees.
Matrix3 (const Vector3<Real>& axis, Real angle);
// Create a tensor product U*V^T.
Matrix3 (const Vector3<Real>& u, const Vector3<Real>& v);
// Assignment.
Matrix3& operator= (const Matrix3& mat);
// Create various matrices.
Matrix3& MakeZero ();
Matrix3& MakeIdentity ();
Matrix3& MakeDiagonal (Real m00, Real m11, Real m22);
Matrix3& MakeRotation (const Vector3<Real>& axis, Real angle);
Matrix3& MakeTensorProduct (const Vector3<Real>& u,
const Vector3<Real>& v);
// Arithmetic operations.
Matrix3 operator+ (const Matrix3& mat) const;
Matrix3 operator- (const Matrix3& mat) const;
Matrix3 operator* (Real scalar) const;
Matrix3 operator/ (Real scalar) const;
Matrix3 operator- () const;
// Arithmetic updates.
Matrix3& operator+= (const Matrix3& mat);
Matrix3& operator-= (const Matrix3& mat);
Matrix3& operator*= (Real scalar);
Matrix3& operator/= (Real scalar);
// M*vec
Vector3<Real> operator* (const Vector3<Real>& vec) const;
// u^T*M*v
Real QForm (const Vector3<Real>& u, const Vector3<Real>& v) const;
// M^T
Matrix3 Transpose () const;
// M*mat
Matrix3 operator* (const Matrix3& mat) const;
// M^T*mat
Matrix3 TransposeTimes (const Matrix3& mat) const;
// M*mat^T
Matrix3 TimesTranspose (const Matrix3& mat) const;
// M^T*mat^T
Matrix3 TransposeTimesTranspose (const Matrix3& mat) const;
// Other operations.
Matrix3 TimesDiagonal (const Vector3<Real>& diag) const; // M*D
Matrix3 DiagonalTimes (const Vector3<Real>& diag) const; // D*M
Matrix3 Inverse (const Real epsilon = (Real)0) const;
Matrix3 Adjoint () const;
Real Determinant () const;
// The matrix must be a rotation for these functions to be valid. The
// last function uses Gram-Schmidt orthonormalization applied to the
// columns of the rotation matrix. The angle must be in radians, not
// degrees.
void ExtractAxisAngle (Vector3<Real>& axis, Real& angle) const;
void Orthonormalize ();
// The matrix must be symmetric. Factor M = R * D * R^T where
// R = [u0|u1|u2] is a rotation matrix with columns u0, u1, and u2 and
// D = diag(d0,d1,d2) is a diagonal matrix whose diagonal entries are d0,
// d1, and d2. The eigenvector u[i] corresponds to eigenvector d[i].
// The eigenvalues are ordered as d0 <= d1 <= d2.
void EigenDecomposition (Matrix3& rot, Matrix3& diag) const;
// Create rotation matrices from Euler angles.
void MakeEulerXYZ (Real xAngle, Real yAngle, Real zAngle);
void MakeEulerXZY (Real xAngle, Real zAngle, Real yAngle);
void MakeEulerYXZ (Real yAngle, Real xAngle, Real zAngle);
void MakeEulerYZX (Real yAngle, Real zAngle, Real xAngle);
void MakeEulerZXY (Real zAngle, Real xAngle, Real yAngle);
void MakeEulerZYX (Real zAngle, Real yAngle, Real xAngle);
void MakeEulerXYX (Real x0Angle, Real yAngle, Real x1Angle);
void MakeEulerXZX (Real x0Angle, Real zAngle, Real x1Angle);
void MakeEulerYXY (Real y0Angle, Real xAngle, Real y1Angle);
void MakeEulerYZY (Real y0Angle, Real zAngle, Real y1Angle);
void MakeEulerZXZ (Real z0Angle, Real xAngle, Real z1Angle);
void MakeEulerZYZ (Real z0Angle, Real yAngle, Real z1Angle);
// Extract Euler angles from rotation matrices.
enum EulerResult
{
// The solution is unique.
EA_UNIQUE,
// The solution is not unique. A sum of angles is constant.
EA_NOT_UNIQUE_SUM,
// The solution is not unique. A difference of angles is constant.
EA_NOT_UNIQUE_DIF
};
// The return values are in the specified ranges:
// xAngle in [-pi,pi], yAngle in [-pi/2,pi/2], zAngle in [-pi,pi]
// When the solution is not unique, zAngle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: zAngle + xAngle = c
// EA_NOT_UNIQUE_DIF: zAngle - xAngle = c
// for some angle c.
EulerResult ExtractEulerXYZ (Real& xAngle, Real& yAngle, Real& zAngle)
const;
// The return values are in the specified ranges:
// xAngle in [-pi,pi], zAngle in [-pi/2,pi/2], yAngle in [-pi,pi]
// When the solution is not unique, yAngle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: yAngle + xAngle = c
// EA_NOT_UNIQUE_DIF: yAngle - xAngle = c
// for some angle c.
EulerResult ExtractEulerXZY (Real& xAngle, Real& zAngle, Real& yAngle)
const;
// The return values are in the specified ranges:
// yAngle in [-pi,pi], xAngle in [-pi/2,pi/2], zAngle in [-pi,pi]
// When the solution is not unique, zAngle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: zAngle + yAngle = c
// EA_NOT_UNIQUE_DIF: zAngle - yAngle = c
// for some angle c.
EulerResult ExtractEulerYXZ (Real& yAngle, Real& xAngle, Real& zAngle)
const;
// The return values are in the specified ranges:
// yAngle in [-pi,pi], zAngle in [-pi/2,pi/2], xAngle in [-pi,pi]
// When the solution is not unique, xAngle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: xAngle + yAngle = c
// EA_NOT_UNIQUE_DIF: xAngle - yAngle = c
// for some angle c.
EulerResult ExtractEulerYZX (Real& yAngle, Real& zAngle, Real& xAngle)
const;
// The return values are in the specified ranges:
// zAngle in [-pi,pi], xAngle in [-pi/2,pi/2], yAngle in [-pi,pi]
// When the solution is not unique, yAngle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: yAngle + zAngle = c
// EA_NOT_UNIQUE_DIF: yAngle - zAngle = c
// for some angle c.
EulerResult ExtractEulerZXY (Real& zAngle, Real& xAngle, Real& yAngle)
const;
// The return values are in the specified ranges:
// zAngle in [-pi,pi], yAngle in [-pi/2,pi/2], xAngle in [-pi,pi]
// When the solution is not unique, xAngle = 0 is/ returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: xAngle + zAngle = c
// EA_NOT_UNIQUE_DIF: xAngle - zAngle = c
// for some angle c.
EulerResult ExtractEulerZYX (Real& zAngle, Real& yAngle, Real& xAngle)
const;
// The return values are in the specified ranges:
// x0Angle in [-pi,pi], yAngle in [0,pi], x1Angle in [-pi,pi]
// When the solution is not unique, x1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: x1Angle + x0Angle = c
// EA_NOT_UNIQUE_DIF: x1Angle - x0Angle = c
// for some angle c.
EulerResult ExtractEulerXYX (Real& x0Angle, Real& yAngle, Real& x1Angle)
const;
// The return values are in the specified ranges:
// x0Angle in [-pi,pi], zAngle in [0,pi], x1Angle in [-pi,pi]
// When the solution is not unique, x1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: x1Angle + x0Angle = c
// EA_NOT_UNIQUE_DIF: x1Angle - x0Angle = c
// for some angle c.
EulerResult ExtractEulerXZX (Real& x0Angle, Real& zAngle, Real& x1Angle)
const;
// The return values are in the specified ranges:
// y0Angle in [-pi,pi], xAngle in [0,pi], y1Angle in [-pi,pi]
// When the solution is not unique, y1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: y1Angle + y0Angle = c
// EA_NOT_UNIQUE_DIF: y1Angle - y0Angle = c
// for some angle c.
EulerResult ExtractEulerYXY (Real& y0Angle, Real& xAngle, Real& y1Angle)
const;
// The return values are in the specified ranges:
// y0Angle in [-pi,pi], zAngle in [0,pi], y1Angle in [-pi,pi]
// When the solution is not unique, y1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: y1Angle + y0Angle = c
// EA_NOT_UNIQUE_DIF: y1Angle - y0Angle = c
// for some angle c.
EulerResult ExtractEulerYZY (Real& y0Angle, Real& zAngle, Real& y1Angle)
const;
// The return values are in the specified ranges:
// z0Angle in [-pi,pi], xAngle in [0,pi], z1Angle in [-pi,pi]
// When the solution is not unique, z1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: z1Angle + z0Angle = c
// EA_NOT_UNIQUE_DIF: z1Angle - z0Angle = c
// for some angle c.
EulerResult ExtractEulerZXZ (Real& z0Angle, Real& xAngle, Real& z1Angle)
const;
// The return values are in the specified ranges:
// z0Angle in [-pi,pi], yAngle in [0,pi], z1Angle in [-pi,pi]
// When the solution is not unique, z1Angle = 0 is returned. Generally,
// the set of solutions is
// EA_NOT_UNIQUE_SUM: z1Angle + z0Angle = c
// EA_NOT_UNIQUE_DIF: z1Angle - z0Angle = c
// for some angle c.
EulerResult ExtractEulerZYZ (Real& z0Angle, Real& yAngle, Real& z1Angle)
const;
// SLERP (spherical linear interpolation) without quaternions. Computes
// R(t) = R0*(Transpose(R0)*R1)^t. If Q is a rotation matrix with
// unit-length axis U and angle A, then Q^t is a rotation matrix with
// unit-length axis U and rotation angle t*A.
Matrix3& Slerp (Real t, const Matrix3& rot0, const Matrix3& rot1);
// Singular value decomposition, M = L*D*Transpose(R), where L and R are
// orthogonal and D is a diagonal matrix whose diagonal entries are
// nonnegative.
void SingularValueDecomposition (Matrix3& left, Matrix3& diag,
Matrix3& rightTranspose) const;
// Polar decomposition, M = Q*S, where Q is orthogonal and S is symmetric.
// This uses the singular value decomposition:
// M = L*D*Transpose(R) = (L*Transpose(R))*(R*D*Transpose(R)) = Q*S
// where Q = L*Transpose(R) and S = R*D*Transpose(R).
void PolarDecomposition (Matrix3& qMat, Matrix3& sMat);
// Factor M = Q*D*U with orthogonal Q, diagonal D, upper triangular U.
void QDUDecomposition (Matrix3& qMat, Matrix3& diag, Matrix3& uMat)
const;
// Special matrices.
WM5_MATHEMATICS_ITEM static const Matrix3 ZERO;
WM5_MATHEMATICS_ITEM static const Matrix3 IDENTITY;
private:
// Support for eigendecomposition. The Tridiagonalize function applies
// a Householder transformation to the matrix. If that transformation
// is the identity (the matrix is already tridiagonal), then the return
// value is 'false'. Otherwise, the transformation is a reflection and
// the return value is 'true'. The QLAlgorithm returns 'true' iff the
// QL iteration scheme converged.
bool Tridiagonalize (Real diagonal[3], Real subdiagonal[2]);
bool QLAlgorithm (Real diagonal[3], Real subdiagonal[2]);
protected:
using Table<3,3,Real>::mEntry;
};
// c * M
template <typename Real>
inline Matrix3<Real> operator* (Real scalar, const Matrix3<Real>& mat);
// v^T * M
template <typename Real>
inline Vector3<Real> operator* (const Vector3<Real>& vec,
const Matrix3<Real>& mat);
#include "Wm5Matrix3.inl"
typedef Matrix3<float> Matrix3f;
typedef Matrix3<double> Matrix3d;
}
#endif
|