// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 2x2, 3x3, and 4x4 transformation matrix templates // #ifndef INCLUDED_IMATHMATRIX_H #define INCLUDED_IMATHMATRIX_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathFun.h" #include "ImathPlatform.h" #include "ImathShear.h" #include "ImathVec.h" #include #include #include #include #include #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings # pragma warning(disable : 4290) #endif IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// Enum used to indicate uninitialized construction of Matrix22, /// Matrix33, Matrix44 enum IMATH_EXPORT_ENUM Uninitialized { UNINITIALIZED }; /// /// 2x2 transformation matrix /// template class IMATH_EXPORT_TEMPLATE_TYPE Matrix22 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[2][2]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE Matrix22 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// /// 1 0 /// 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22() IMATH_NOEXCEPT; /// Initialize to scalar constant: /// /// a a /// a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (T a) IMATH_NOEXCEPT; /// Construct from 2x2 array: /// /// a[0][0] a[0][1] /// a[1][0] a[1][1] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (const T a[2][2]) IMATH_NOEXCEPT; /// Construct from given scalar values: /// /// a b /// c d IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (T a, T b, T c, T d) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (const Matrix22& v) IMATH_NOEXCEPT; /// Construct from Matrix22 of another base type template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix22 (const Matrix22& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator= (const Matrix22& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix22() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template::value)> IMATH_HOSTDEVICE explicit Matrix22 (const M& m) : Matrix22(T(m[0][0]), T(m[0][1]), T(m[1][0]), T(m[1][1])) { } template::value)> IMATH_HOSTDEVICE const Matrix22& operator= (const M& m) { *this = Matrix22(T(m[0][0]), T(m[0][1]), T(m[1][0]), T(m[1][1])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Matrix22& v) const IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22& setValue (const Matrix22& v) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22& setTheMatrix (const Matrix22& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix22& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix22& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix22& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix22& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator+= (const Matrix22& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix22 operator+ (const Matrix22& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator-= (const Matrix22& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix22 operator- (const Matrix22& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix22 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix22 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix22 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator*= (const Matrix22& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 operator* (const Matrix22& v) const IMATH_NOEXCEPT; /// Vector * matrix multiplication /// @param[in] src Input vector /// @param[out] dst transformed vector template IMATH_HOSTDEVICE void multDirMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix22 transposed() const IMATH_NOEXCEPT; /// Invert in place /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix22& invert (bool singExc); /// Invert in place /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& invert() IMATH_NOEXCEPT; /// Return the inverse, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix22 inverse (bool singExc) const; /// Return the inverse, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 inverse() const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE constexpr T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by r (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE const Matrix22& setRotation (S r) IMATH_NOEXCEPT; /// Rotate the given matrix by r (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& rotate (S r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& setScale (const Vec2& s) IMATH_NOEXCEPT; // Scale the matrix by s /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& scale (const Vec2& s) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 2. IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 2; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec2 BaseVecType; }; /// /// 3x3 transformation matrix /// template class IMATH_EXPORT_TEMPLATE_TYPE Matrix33 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[3][3]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE Matrix33 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// 1 0 0 /// 0 1 0 /// 0 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33() IMATH_NOEXCEPT; /// Initialize to scalar constant /// a a a /// a a a /// a a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (T a) IMATH_NOEXCEPT; /// Construct from 3x3 array /// a[0][0] a[0][1] a[0][2] /// a[1][0] a[1][1] a[1][2] /// a[2][0] a[2][1] a[2][2] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (const T a[3][3]) IMATH_NOEXCEPT; /// Construct from given scalar values /// a b c /// d e f /// g h i IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (const Matrix33& v) IMATH_NOEXCEPT; /// Construct from Matrix33 of another base type template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix33 (const Matrix33& v) IMATH_NOEXCEPT; /// Assignment operator IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator= (const Matrix33& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix33() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template::value)> IMATH_HOSTDEVICE explicit Matrix33 (const M& m) : Matrix33(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[2][0]), T(m[2][1]), T(m[2][2])) { } /// Interoperability assignment from another type that behaves as if it /// were an equivalent matrix. template::value)> IMATH_HOSTDEVICE const Matrix33& operator= (const M& m) { *this = Matrix33(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[2][0]), T(m[2][1]), T(m[2][2])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Matrix33& v) const IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33& setValue (const Matrix33& v) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33& setTheMatrix (const Matrix33& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix33& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix33& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix33& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix33& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator+= (const Matrix33& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix33 operator+ (const Matrix33& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator-= (const Matrix33& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix33 operator- (const Matrix33& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix33 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix33 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix33 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator*= (const Matrix33& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 operator* (const Matrix33& v) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: a homogeneous transformation /// by computing Vec3 (src.x, src.y, 1) * m and dividing by the /// result's third element. /// @param[in] src The input vector /// @param[out] dst The output vector template IMATH_HOSTDEVICE void multVecMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: multiply `src` by the upper left 2x2 /// submatrix, ignoring the rest of matrix. /// @param[in] src The input vector /// @param[out] dst The output vector template IMATH_HOSTDEVICE void multDirMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity matrix IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix33 transposed() const IMATH_NOEXCEPT; /// Invert in place using the determinant. /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix33& invert (bool singExc); /// Invert in place using the determinant. /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& invert() IMATH_NOEXCEPT; /// Return the inverse using the determinant, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix33 inverse (bool singExc) const; /// Return the inverse using the determinant, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 inverse() const IMATH_NOEXCEPT; /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this const Matrix33& gjInvert (bool singExc); /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @return const reference to this IMATH_HOSTDEVICE const Matrix33& gjInvert() IMATH_NOEXCEPT; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified. Significantly slower but more accurate than inverse(). Matrix33 gjInverse (bool singExc) const; /// Return the inverse using the Gauss-Jordan method. Significantly slower, /// leaving this unmodified. Slower but more accurate than inverse(). IMATH_HOSTDEVICE Matrix33 gjInverse() const IMATH_NOEXCEPT; /// Calculate the matrix minor of the (r,c) element IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T minorOf (const int r, const int c) const IMATH_NOEXCEPT; /// Build a minor using the specified rows and columns IMATH_HOSTDEVICE constexpr T fastMinor (const int r0, const int r1, const int c0, const int c1) const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE constexpr T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by r (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE const Matrix33& setRotation (S r) IMATH_NOEXCEPT; // Rotate the given matrix by r (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& rotate (S r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setScale (const Vec2& s) IMATH_NOEXCEPT; /// Scale the matrix by s /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& scale (const Vec2& s) IMATH_NOEXCEPT; /// Set matrix to translation by given vector /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setTranslation (const Vec2& t) IMATH_NOEXCEPT; /// Return the translation component IMATH_HOSTDEVICE constexpr Vec2 translation() const IMATH_NOEXCEPT; /// Translate the matrix by t /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& translate (const Vec2& t) IMATH_NOEXCEPT; /// Set matrix to shear x for each y coord. by given factor xy /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setShear (const S& h) IMATH_NOEXCEPT; /// Set matrix to shear x for each y coord. by given factor h.x /// and to shear y for each x coord. by given factor h.y /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setShear (const Vec2& h) IMATH_NOEXCEPT; /// Shear the matrix in x for each y coord. by given factor xy /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& shear (const S& xy) IMATH_NOEXCEPT; /// Shear the matrix in x for each y coord. by given factor xy /// and shear y for each x coord. by given factor yx /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& shear (const Vec2& h) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 3. IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 3; } /// The base type: In templates that accept a parameter `V` (could be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec3 BaseVecType; }; /// /// 4x4 transformation matrix /// template class IMATH_EXPORT_TEMPLATE_TYPE Matrix44 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[4][4]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE constexpr Matrix44 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// 1 0 0 0 /// 0 1 0 0 /// 0 0 1 0 /// 0 0 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44() IMATH_NOEXCEPT; /// Initialize to scalar constant /// a a a a /// a a a a /// a a a a /// a a a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (T a) IMATH_NOEXCEPT; /// Construct from 4x4 array /// a[0][0] a[0][1] a[0][2] a[0][3] /// a[1][0] a[1][1] a[1][2] a[1][3] /// a[2][0] a[2][1] a[2][2] a[2][3] /// a[3][0] a[3][1] a[3][2] a[3][3] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (const T a[4][4]) IMATH_NOEXCEPT; /// Construct from given scalar values /// a b c d /// e f g h /// i j k l /// m n o p IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p) IMATH_NOEXCEPT; /// Construct from a 3x3 rotation matrix and a translation vector /// r r r 0 /// r r r 0 /// r r r 0 /// t t t 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (Matrix33 r, Vec3 t) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (const Matrix44& v) IMATH_NOEXCEPT; /// Construct from Matrix44 of another base type template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix44 (const Matrix44& v) IMATH_NOEXCEPT; /// Assignment operator IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator= (const Matrix44& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix44() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template::value)> IMATH_HOSTDEVICE explicit Matrix44 (const M& m) : Matrix44(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[0][3]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[1][3]), T(m[2][0]), T(m[2][1]), T(m[2][2]), T(m[2][3]), T(m[3][0]), T(m[3][1]), T(m[3][2]), T(m[3][3])) { } /// Interoperability assignment from another type that behaves as if it /// were an equivalent matrix. template::value)> IMATH_HOSTDEVICE const Matrix44& operator= (const M& m) { *this = Matrix44(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[0][3]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[1][3]), T(m[2][0]), T(m[2][1]), T(m[2][2]), T(m[2][3]), T(m[3][0]), T(m[3][1]), T(m[3][2]), T(m[3][3])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Matrix44& v) const IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44& setValue (const Matrix44& v) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44& setTheMatrix (const Matrix44& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix44& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix44& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix44& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix44& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator+= (const Matrix44& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix44 operator+ (const Matrix44& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator-= (const Matrix44& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix44 operator- (const Matrix44& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix44 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix44 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix44 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator*= (const Matrix44& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 operator* (const Matrix44& v) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication: compute c = a * b IMATH_HOSTDEVICE static void multiply (const Matrix44& a, // assumes that const Matrix44& b, // &a != &c and Matrix44& c) IMATH_NOEXCEPT; // &b != &c. /// Matrix-matrix multiplication returning a result. IMATH_HOSTDEVICE static IMATH_CONSTEXPR14 Matrix44 multiply (const Matrix44& a, const Matrix44& b) IMATH_NOEXCEPT; /// Vector-matrix multiplication: a homogeneous transformation /// by computing Vec3 (src.x, src.y, src.z, 1) * m and dividing by the /// result's third element. /// @param[in] src The input vector /// @param[out] dst The output vector template IMATH_HOSTDEVICE void multVecMatrix (const Vec3& src, Vec3& dst) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: multiply `src` by the upper left 2x2 /// submatrix, ignoring the rest of matrix. /// @param[in] src The input vector /// @param[out] dst The output vector template IMATH_HOSTDEVICE void multDirMatrix (const Vec3& src, Vec3& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity matrix IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix44 transposed() const IMATH_NOEXCEPT; /// Invert in place using the determinant. /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix44& invert (bool singExc); /// Invert in place using the determinant. /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& invert() IMATH_NOEXCEPT; /// Return the inverse using the determinant, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix44 inverse (bool singExc) const; /// Return the inverse using the determinant, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 inverse() const IMATH_NOEXCEPT; /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix44& gjInvert (bool singExc); /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& gjInvert() IMATH_NOEXCEPT; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified. Significantly slower but more accurate than inverse(). Matrix44 gjInverse (bool singExc) const; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified Significantly slower but more accurate than inverse(). IMATH_HOSTDEVICE Matrix44 gjInverse() const IMATH_NOEXCEPT; /// Calculate the matrix minor of the (r,c) element IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T minorOf (const int r, const int c) const IMATH_NOEXCEPT; /// Build a minor using the specified rows and columns IMATH_HOSTDEVICE constexpr T fastMinor (const int r0, const int r1, const int r2, const int c0, const int c1, const int c2) const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by XYZ euler angles (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE const Matrix44& setEulerAngles (const Vec3& r) IMATH_NOEXCEPT; /// Set matrix to rotation around given axis by given angle (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setAxisAngle (const Vec3& ax, S ang) IMATH_NOEXCEPT; /// Rotate the matrix by XYZ euler angles in r (in radians) /// @return const referenced to this template IMATH_HOSTDEVICE const Matrix44& rotate (const Vec3& r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setScale (const Vec3& s) IMATH_NOEXCEPT; /// Scale the matrix by s /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& scale (const Vec3& s) IMATH_NOEXCEPT; /// Set matrix to translation by given vector /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setTranslation (const Vec3& t) IMATH_NOEXCEPT; /// Return translation component IMATH_HOSTDEVICE constexpr const Vec3 translation() const IMATH_NOEXCEPT; /// Translate the matrix by t /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& translate (const Vec3& t) IMATH_NOEXCEPT; /// Set matrix to shear by given vector h. The resulting matrix /// - will shear x for each y coord. by a factor of h[0] ; /// - will shear x for each z coord. by a factor of h[1] ; /// - will shear y for each z coord. by a factor of h[2] . /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setShear (const Vec3& h) IMATH_NOEXCEPT; /// Set matrix to shear by given factors. The resulting matrix /// - will shear x for each y coord. by a factor of h.xy ; /// - will shear x for each z coord. by a factor of h.xz ; /// - will shear y for each z coord. by a factor of h.yz ; /// - will shear y for each x coord. by a factor of h.yx ; /// - will shear z for each x coord. by a factor of h.zx ; /// - will shear z for each y coord. by a factor of h.zy . /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setShear (const Shear6& h) IMATH_NOEXCEPT; /// Shear the matrix by given vector. The composed matrix /// will be `shear` * `this`, where the shear matrix ... /// - will shear x for each y coord. by a factor of h[0] ; /// - will shear x for each z coord. by a factor of h[1] ; /// - will shear y for each z coord. by a factor of h[2] . /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& shear (const Vec3& h) IMATH_NOEXCEPT; /// Shear the matrix by the given factors. The composed matrix /// will be `shear` * `this`, where the shear matrix ... /// - will shear x for each y coord. by a factor of h.xy ; /// - will shear x for each z coord. by a factor of h.xz ; /// - will shear y for each z coord. by a factor of h.yz ; /// - will shear y for each x coord. by a factor of h.yx ; /// - will shear z for each x coord. by a factor of h.zx ; /// - will shear z for each y coord. by a factor of h.zy . /// @return const referenced to this template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& shear (const Shear6& h) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 4 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; } /// The base type: In templates that accept a parameter `V` (could be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec4 BaseVecType; }; /// Stream output, as: /// (m00 m01 /// m10 m11) template std::ostream& operator<< (std::ostream& s, const Matrix22& m); /// Stream output, as: /// (m00 m01 m02 /// m10 m11 m12 /// m20 m21 m22) template std::ostream& operator<< (std::ostream& s, const Matrix33& m); /// Stream output, as: /// /// (m00 m01 m02 m03 /// m10 m11 m12 m13 /// m20 m21 m22 m23 /// m30 m31 m32 m33) template std::ostream& operator<< (std::ostream& s, const Matrix44& m); //--------------------------------------------- // Vector-times-matrix multiplication operators //--------------------------------------------- /// Vector-matrix multiplication: v *= m template IMATH_HOSTDEVICE inline const Vec2& operator*= (Vec2& v, const Matrix22& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template IMATH_HOSTDEVICE inline Vec2 operator* (const Vec2& v, const Matrix22& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template IMATH_HOSTDEVICE inline const Vec2& operator*= (Vec2& v, const Matrix33& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template IMATH_HOSTDEVICE inline Vec2 operator* (const Vec2& v, const Matrix33& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template IMATH_HOSTDEVICE inline const Vec3& operator*= (Vec3& v, const Matrix33& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template IMATH_HOSTDEVICE inline Vec3 operator* (const Vec3& v, const Matrix33& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template IMATH_HOSTDEVICE inline const Vec3& operator*= (Vec3& v, const Matrix44& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template IMATH_HOSTDEVICE inline Vec3 operator* (const Vec3& v, const Matrix44& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template IMATH_HOSTDEVICE inline const Vec4& operator*= (Vec4& v, const Matrix44& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template IMATH_HOSTDEVICE inline Vec4 operator* (const Vec4& v, const Matrix44& m) IMATH_NOEXCEPT; //------------------------- // Typedefs for convenience //------------------------- /// 2x2 matrix of float typedef Matrix22 M22f; /// 2x2 matrix of double typedef Matrix22 M22d; /// 3x3 matrix of float typedef Matrix33 M33f; /// 3x3 matrix of double typedef Matrix33 M33d; /// 4x4 matrix of float typedef Matrix44 M44f; /// 4x4 matrix of double typedef Matrix44 M44d; //--------------------------- // Implementation of Matrix22 //--------------------------- template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix22::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE inline const T* Matrix22::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[1][0] = 0; x[1][1] = 1; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[1][0] = a; x[1][1] = a; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22 (const T a[2][2]) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, a, sizeof (x)); // we do this: x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22 (T a, T b, T c, T d) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[1][0] = c; x[1][1] = d; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22 (const Matrix22& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so we don't do this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22::Matrix22 (const Matrix22& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator= (const Matrix22& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so we don't do this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[1][0] = a; x[1][1] = a; return *this; } template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix22::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template IMATH_HOSTDEVICE inline const T* Matrix22::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template template IMATH_HOSTDEVICE inline void Matrix22::getValue (Matrix22& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22& Matrix22::setValue (const Matrix22& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22& Matrix22::setTheMatrix (const Matrix22& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template IMATH_HOSTDEVICE inline void Matrix22::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[1][0] = 0; x[1][1] = 1; } template IMATH_HOSTDEVICE constexpr inline bool Matrix22::operator== (const Matrix22& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1]; } template IMATH_HOSTDEVICE constexpr inline bool Matrix22::operator!= (const Matrix22& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix22::equalWithAbsError (const Matrix22& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this).x[i][j], m.x[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix22::equalWithRelError (const Matrix22& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this).x[i][j], m.x[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator+= (const Matrix22& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[1][0] += a; x[1][1] += a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::operator+ (const Matrix22& v) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator-= (const Matrix22& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[1][0] -= a; x[1][1] -= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::operator- (const Matrix22& v) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1]); } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::operator-() const IMATH_NOEXCEPT { return Matrix22 (-x[0][0], -x[0][1], -x[1][0], -x[1][1]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[1][0] *= a; x[1][1] *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::operator* (T a) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] * a, x[0][1] * a, x[1][0] * a, x[1][1] * a); } /// Matrix-scalar multiplication template IMATH_HOSTDEVICE inline Matrix22 operator* (T a, const Matrix22& v) IMATH_NOEXCEPT { return v * a; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator*= (const Matrix22& v) IMATH_NOEXCEPT { Matrix22 tmp (T (0)); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) tmp.x[i][j] += x[i][k] * v.x[k][j]; *this = tmp; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22 Matrix22::operator* (const Matrix22& v) const IMATH_NOEXCEPT { Matrix22 tmp (T (0)); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) tmp.x[i][j] += x[i][k] * v.x[k][j]; return tmp; } template template IMATH_HOSTDEVICE inline void Matrix22::multDirMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT { S a, b; a = src.x * x[0][0] + src.y * x[1][0]; b = src.x * x[0][1] + src.y * x[1][1]; dst.x = a; dst.y = b; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[1][0] /= a; x[1][1] /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::operator/ (T a) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] / a, x[0][1] / a, x[1][0] / a, x[1][1] / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::transpose() IMATH_NOEXCEPT { Matrix22 tmp (x[0][0], x[1][0], x[0][1], x[1][1]); *this = tmp; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix22 Matrix22::transposed() const IMATH_NOEXCEPT { return Matrix22 (x[0][0], x[1][0], x[0][1], x[1][1]); } template IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::invert (bool singExc) { *this = inverse (singExc); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template IMATH_CONSTEXPR14 inline Matrix22 Matrix22::inverse (bool singExc) const { Matrix22 s (x[1][1], -x[0][1], -x[1][0], x[0][0]); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix22(); } } } } return s; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix22 Matrix22::inverse() const IMATH_NOEXCEPT { Matrix22 s (x[1][1], -x[0][1], -x[1][0], x[0][0]); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { return Matrix22(); } } } } return s; } template IMATH_HOSTDEVICE constexpr inline T Matrix22::determinant() const IMATH_NOEXCEPT { return x[0][0] * x[1][1] - x[1][0] * x[0][1]; } template template IMATH_HOSTDEVICE inline const Matrix22& Matrix22::setRotation (S r) IMATH_NOEXCEPT { S cos_r, sin_r; cos_r = cos ((T) r); sin_r = sin ((T) r); x[0][0] = cos_r; x[0][1] = sin_r; x[1][0] = -sin_r; x[1][1] = cos_r; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::rotate (S r) IMATH_NOEXCEPT { *this *= Matrix22().setRotation (r); return *this; } template IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to: // | s 0 | // | 0 s | // x[0][0] = s; x[0][1] = static_cast (0); x[1][0] = static_cast (0); x[1][1] = s; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::setScale (const Vec2& s) IMATH_NOEXCEPT { // // Set the matrix to: // | s.x 0 | // | 0 s.y | // x[0][0] = s.x; x[0][1] = static_cast (0); x[1][0] = static_cast (0); x[1][1] = s.y; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix22& Matrix22::scale (const Vec2& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; return *this; } //--------------------------- // Implementation of Matrix33 //--------------------------- template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix33::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE inline const T* Matrix33::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE inline IMATH_CONSTEXPR14 Matrix33::Matrix33() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33::Matrix33 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33::Matrix33 (const T a[3][3]) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, a, sizeof (x)); // we do this: x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[0][2] = a[0][2]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; x[1][2] = a[1][2]; x[2][0] = a[2][0]; x[2][1] = a[2][1]; x[2][2] = a[2][2]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33::Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[0][2] = c; x[1][0] = d; x[1][1] = e; x[1][2] = f; x[2][0] = g; x[2][1] = h; x[2][2] = i; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33::Matrix33 (const Matrix33& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33::Matrix33 (const Matrix33& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[0][2] = T (v.x[0][2]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); x[1][2] = T (v.x[1][2]); x[2][0] = T (v.x[2][0]); x[2][1] = T (v.x[2][1]); x[2][2] = T (v.x[2][2]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator= (const Matrix33& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; return *this; } template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix33::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template IMATH_HOSTDEVICE inline const T* Matrix33::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template template IMATH_HOSTDEVICE inline void Matrix33::getValue (Matrix33& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[0][2] = x[0][2]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; v.x[1][2] = x[1][2]; v.x[2][0] = x[2][0]; v.x[2][1] = x[2][1]; v.x[2][2] = x[2][2]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33& Matrix33::setValue (const Matrix33& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33& Matrix33::setTheMatrix (const Matrix33& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template IMATH_HOSTDEVICE inline void Matrix33::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; } template IMATH_HOSTDEVICE constexpr inline bool Matrix33::operator== (const Matrix33& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[0][2] == v.x[0][2] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1] && x[1][2] == v.x[1][2] && x[2][0] == v.x[2][0] && x[2][1] == v.x[2][1] && x[2][2] == v.x[2][2]; } template IMATH_HOSTDEVICE constexpr inline bool Matrix33::operator!= (const Matrix33& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[0][2] != v.x[0][2] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1] || x[1][2] != v.x[1][2] || x[2][0] != v.x[2][0] || x[2][1] != v.x[2][1] || x[2][2] != v.x[2][2]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix33::equalWithAbsError (const Matrix33& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix33::equalWithRelError (const Matrix33& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator+= (const Matrix33& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[0][2] += v.x[0][2]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; x[1][2] += v.x[1][2]; x[2][0] += v.x[2][0]; x[2][1] += v.x[2][1]; x[2][2] += v.x[2][2]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[0][2] += a; x[1][0] += a; x[1][1] += a; x[1][2] += a; x[2][0] += a; x[2][1] += a; x[2][2] += a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::operator+ (const Matrix33& v) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[0][2] + v.x[0][2], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1], x[1][2] + v.x[1][2], x[2][0] + v.x[2][0], x[2][1] + v.x[2][1], x[2][2] + v.x[2][2]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator-= (const Matrix33& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[0][2] -= v.x[0][2]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; x[1][2] -= v.x[1][2]; x[2][0] -= v.x[2][0]; x[2][1] -= v.x[2][1]; x[2][2] -= v.x[2][2]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[0][2] -= a; x[1][0] -= a; x[1][1] -= a; x[1][2] -= a; x[2][0] -= a; x[2][1] -= a; x[2][2] -= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::operator- (const Matrix33& v) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[0][2] - v.x[0][2], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1], x[1][2] - v.x[1][2], x[2][0] - v.x[2][0], x[2][1] - v.x[2][1], x[2][2] - v.x[2][2]); } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::operator-() const IMATH_NOEXCEPT { return Matrix33 (-x[0][0], -x[0][1], -x[0][2], -x[1][0], -x[1][1], -x[1][2], -x[2][0], -x[2][1], -x[2][2]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[0][2] = -x[0][2]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; x[1][2] = -x[1][2]; x[2][0] = -x[2][0]; x[2][1] = -x[2][1]; x[2][2] = -x[2][2]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[0][2] *= a; x[1][0] *= a; x[1][1] *= a; x[1][2] *= a; x[2][0] *= a; x[2][1] *= a; x[2][2] *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::operator* (T a) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] * a, x[0][1] * a, x[0][2] * a, x[1][0] * a, x[1][1] * a, x[1][2] * a, x[2][0] * a, x[2][1] * a, x[2][2] * a); } /// Matrix-scalar multiplication template IMATH_HOSTDEVICE inline Matrix33 constexpr operator* (T a, const Matrix33& v) IMATH_NOEXCEPT { return v * a; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator*= (const Matrix33& v) IMATH_NOEXCEPT { // Avoid initializing with 0 values before immediately overwriting them, // and unroll all loops for the best autovectorization. Matrix33 tmp(IMATH_INTERNAL_NAMESPACE::UNINITIALIZED); tmp.x[0][0] = x[0][0] * v.x[0][0] + x[0][1] * v.x[1][0] + x[0][2] * v.x[2][0]; tmp.x[0][1] = x[0][0] * v.x[0][1] + x[0][1] * v.x[1][1] + x[0][2] * v.x[2][1]; tmp.x[0][2] = x[0][0] * v.x[0][2] + x[0][1] * v.x[1][2] + x[0][2] * v.x[2][2]; tmp.x[1][0] = x[1][0] * v.x[0][0] + x[1][1] * v.x[1][0] + x[1][2] * v.x[2][0]; tmp.x[1][1] = x[1][0] * v.x[0][1] + x[1][1] * v.x[1][1] + x[1][2] * v.x[2][1]; tmp.x[1][2] = x[1][0] * v.x[0][2] + x[1][1] * v.x[1][2] + x[1][2] * v.x[2][2]; tmp.x[2][0] = x[2][0] * v.x[0][0] + x[2][1] * v.x[1][0] + x[2][2] * v.x[2][0]; tmp.x[2][1] = x[2][0] * v.x[0][1] + x[2][1] * v.x[1][1] + x[2][2] * v.x[2][1]; tmp.x[2][2] = x[2][0] * v.x[0][2] + x[2][1] * v.x[1][2] + x[2][2] * v.x[2][2]; *this = tmp; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33 Matrix33::operator* (const Matrix33& v) const IMATH_NOEXCEPT { // Avoid initializing with 0 values before immediately overwriting them, // and unroll all loops for the best autovectorization. Matrix33 tmp(IMATH_INTERNAL_NAMESPACE::UNINITIALIZED); tmp.x[0][0] = x[0][0] * v.x[0][0] + x[0][1] * v.x[1][0] + x[0][2] * v.x[2][0]; tmp.x[0][1] = x[0][0] * v.x[0][1] + x[0][1] * v.x[1][1] + x[0][2] * v.x[2][1]; tmp.x[0][2] = x[0][0] * v.x[0][2] + x[0][1] * v.x[1][2] + x[0][2] * v.x[2][2]; tmp.x[1][0] = x[1][0] * v.x[0][0] + x[1][1] * v.x[1][0] + x[1][2] * v.x[2][0]; tmp.x[1][1] = x[1][0] * v.x[0][1] + x[1][1] * v.x[1][1] + x[1][2] * v.x[2][1]; tmp.x[1][2] = x[1][0] * v.x[0][2] + x[1][1] * v.x[1][2] + x[1][2] * v.x[2][2]; tmp.x[2][0] = x[2][0] * v.x[0][0] + x[2][1] * v.x[1][0] + x[2][2] * v.x[2][0]; tmp.x[2][1] = x[2][0] * v.x[0][1] + x[2][1] * v.x[1][1] + x[2][2] * v.x[2][1]; tmp.x[2][2] = x[2][0] * v.x[0][2] + x[2][1] * v.x[1][2] + x[2][2] * v.x[2][2]; return tmp; } template template IMATH_HOSTDEVICE inline void Matrix33::multVecMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT { S a, b, w; a = src.x * x[0][0] + src.y * x[1][0] + x[2][0]; b = src.x * x[0][1] + src.y * x[1][1] + x[2][1]; w = src.x * x[0][2] + src.y * x[1][2] + x[2][2]; dst.x = a / w; dst.y = b / w; } template template IMATH_HOSTDEVICE inline void Matrix33::multDirMatrix (const Vec2& src, Vec2& dst) const IMATH_NOEXCEPT { S a, b; a = src.x * x[0][0] + src.y * x[1][0]; b = src.x * x[0][1] + src.y * x[1][1]; dst.x = a; dst.y = b; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[0][2] /= a; x[1][0] /= a; x[1][1] /= a; x[1][2] /= a; x[2][0] /= a; x[2][1] /= a; x[2][2] /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::operator/ (T a) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] / a, x[0][1] / a, x[0][2] / a, x[1][0] / a, x[1][1] / a, x[1][2] / a, x[2][0] / a, x[2][1] / a, x[2][2] / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::transpose() IMATH_NOEXCEPT { Matrix33 tmp (x[0][0], x[1][0], x[2][0], x[0][1], x[1][1], x[2][1], x[0][2], x[1][2], x[2][2]); *this = tmp; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix33 Matrix33::transposed() const IMATH_NOEXCEPT { return Matrix33 (x[0][0], x[1][0], x[2][0], x[0][1], x[1][1], x[2][1], x[0][2], x[1][2], x[2][2]); } template const inline Matrix33& Matrix33::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; } template IMATH_HOSTDEVICE const inline Matrix33& Matrix33::gjInvert() IMATH_NOEXCEPT { *this = gjInverse(); return *this; } template inline Matrix33 Matrix33::gjInverse (bool singExc) const { int i, j, k; Matrix33 s; Matrix33 t (*this); // Forward elimination for (i = 0; i < 2; i++) { int pivot = i; T pivotsize = t.x[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 3; j++) { T tmp = t.x[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix33(); } if (pivot != i) { for (j = 0; j < 3; j++) { T tmp; tmp = t.x[i][j]; t.x[i][j] = t.x[pivot][j]; t.x[pivot][j] = tmp; tmp = s.x[i][j]; s.x[i][j] = s.x[pivot][j]; s.x[pivot][j] = tmp; } } for (j = i + 1; j < 3; j++) { T f = t.x[j][i] / t.x[i][i]; for (k = 0; k < 3; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } // Backward substitution for (i = 2; i >= 0; --i) { T f; if ((f = t[i][i]) == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix33(); } for (j = 0; j < 3; j++) { t.x[i][j] /= f; s.x[i][j] /= f; } for (j = 0; j < i; j++) { f = t.x[j][i]; for (k = 0; k < 3; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } return s; } template IMATH_HOSTDEVICE inline Matrix33 Matrix33::gjInverse() const IMATH_NOEXCEPT { int i, j, k; Matrix33 s; Matrix33 t (*this); // Forward elimination for (i = 0; i < 2; i++) { int pivot = i; T pivotsize = t.x[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 3; j++) { T tmp = t.x[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { return Matrix33(); } if (pivot != i) { for (j = 0; j < 3; j++) { T tmp; tmp = t.x[i][j]; t.x[i][j] = t.x[pivot][j]; t.x[pivot][j] = tmp; tmp = s.x[i][j]; s.x[i][j] = s.x[pivot][j]; s.x[pivot][j] = tmp; } } for (j = i + 1; j < 3; j++) { T f = t.x[j][i] / t.x[i][i]; for (k = 0; k < 3; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } // Backward substitution for (i = 2; i >= 0; --i) { T f; if ((f = t.x[i][i]) == 0) { return Matrix33(); } for (j = 0; j < 3; j++) { t.x[i][j] /= f; s.x[i][j] /= f; } for (j = 0; j < i; j++) { f = t.x[j][i]; for (k = 0; k < 3; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } return s; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::invert (bool singExc) { *this = inverse (singExc); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template IMATH_CONSTEXPR14 inline Matrix33 Matrix33::inverse (bool singExc) const { if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) { Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1]); T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix33(); } } } } return s; } else { Matrix33 s (x[1][1], -x[0][1], 0, -x[1][0], x[0][0], 0, 0, 0, 1); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix33(); } } } } s.x[2][0] = -x[2][0] * s.x[0][0] - x[2][1] * s.x[1][0]; s.x[2][1] = -x[2][0] * s.x[0][1] - x[2][1] * s.x[1][1]; return s; } } template IMATH_HOSTDEVICE IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix33 Matrix33::inverse() const IMATH_NOEXCEPT { if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) { Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1]); T r = x[0][0] * s.x[0][0] + x[0][1] * s.x[1][0] + x[0][2] * s.x[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { return Matrix33(); } } } } return s; } else { Matrix33 s (x[1][1], -x[0][1], 0, -x[1][0], x[0][0], 0, 0, 0, 1); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { return Matrix33(); } } } } s.x[2][0] = -x[2][0] * s.x[0][0] - x[2][1] * s.x[1][0]; s.x[2][1] = -x[2][0] * s.x[0][1] - x[2][1] * s.x[1][1]; return s; } } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Matrix33::minorOf (const int r, const int c) const IMATH_NOEXCEPT { int r0 = 0 + (r < 1 ? 1 : 0); int r1 = 1 + (r < 2 ? 1 : 0); int c0 = 0 + (c < 1 ? 1 : 0); int c1 = 1 + (c < 2 ? 1 : 0); return x[r0][c0] * x[r1][c1] - x[r1][c0] * x[r0][c1]; } template IMATH_HOSTDEVICE constexpr inline T Matrix33::fastMinor (const int r0, const int r1, const int c0, const int c1) const IMATH_NOEXCEPT { return x[r0][c0] * x[r1][c1] - x[r0][c1] * x[r1][c0]; } template IMATH_HOSTDEVICE constexpr inline T Matrix33::determinant() const IMATH_NOEXCEPT { return x[0][0] * (x[1][1] * x[2][2] - x[1][2] * x[2][1]) + x[0][1] * (x[1][2] * x[2][0] - x[1][0] * x[2][2]) + x[0][2] * (x[1][0] * x[2][1] - x[1][1] * x[2][0]); } template template IMATH_HOSTDEVICE inline const Matrix33& Matrix33::setRotation (S r) IMATH_NOEXCEPT { S cos_r, sin_r; cos_r = cos ((T) r); sin_r = sin ((T) r); x[0][0] = cos_r; x[0][1] = sin_r; x[0][2] = 0; x[1][0] = -sin_r; x[1][1] = cos_r; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::rotate (S r) IMATH_NOEXCEPT { *this *= Matrix33().setRotation (r); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to a 2D homogeneous transform scale: // | s 0 0 | // | 0 s 0 | // | 0 0 1 | // x[0][0] = s; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = s; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::setScale (const Vec2& s) IMATH_NOEXCEPT { // // Set the matrix to a 2D homogeneous transform scale: // | s.x 0 0 | // | 0 s.y 0 | // | 0 0 1 | // x[0][0] = s.x; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = s.y; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::scale (const Vec2& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[0][2] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; x[1][2] *= s.y; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::setTranslation (const Vec2& t) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = t.x; x[2][1] = t.y; x[2][2] = 1; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec2 Matrix33::translation() const IMATH_NOEXCEPT { return Vec2 (x[2][0], x[2][1]); } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::translate (const Vec2& t) IMATH_NOEXCEPT { x[2][0] += t.x * x[0][0] + t.y * x[1][0]; x[2][1] += t.x * x[0][1] + t.y * x[1][1]; x[2][2] += t.x * x[0][2] + t.y * x[1][2]; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::setShear (const S& xy) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = xy; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::setShear (const Vec2& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = h.y; x[0][2] = 0; x[1][0] = h.x; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::shear (const S& xy) IMATH_NOEXCEPT { // // In this case, we don't need a temp. copy of the matrix // because we never use a value on the RHS after we've // changed it on the LHS. // x[1][0] += xy * x[0][0]; x[1][1] += xy * x[0][1]; x[1][2] += xy * x[0][2]; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix33& Matrix33::shear (const Vec2& h) IMATH_NOEXCEPT { Matrix33 P (*this); x[0][0] = P.x[0][0] + h.y * P.x[1][0]; x[0][1] = P.x[0][1] + h.y * P.x[1][1]; x[0][2] = P.x[0][2] + h.y * P.x[1][2]; x[1][0] = P.x[1][0] + h.x * P.x[0][0]; x[1][1] = P.x[1][1] + h.x * P.x[0][1]; x[1][2] = P.x[1][2] + h.x * P.x[0][2]; return *this; } //--------------------------- // Implementation of Matrix44 //--------------------------- template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix44::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE inline const T* Matrix44::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[0][3] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[1][3] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; x[2][3] = a; x[3][0] = a; x[3][1] = a; x[3][2] = a; x[3][3] = a; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44 (const T a[4][4]) IMATH_NOEXCEPT { x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[0][2] = a[0][2]; x[0][3] = a[0][3]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; x[1][2] = a[1][2]; x[1][3] = a[1][3]; x[2][0] = a[2][0]; x[2][1] = a[2][1]; x[2][2] = a[2][2]; x[2][3] = a[2][3]; x[3][0] = a[3][0]; x[3][1] = a[3][1]; x[3][2] = a[3][2]; x[3][3] = a[3][3]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44< T>::Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[0][2] = c; x[0][3] = d; x[1][0] = e; x[1][1] = f; x[1][2] = g; x[1][3] = h; x[2][0] = i; x[2][1] = j; x[2][2] = k; x[2][3] = l; x[3][0] = m; x[3][1] = n; x[3][2] = o; x[3][3] = p; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44 (Matrix33 r, Vec3 t) IMATH_NOEXCEPT { x[0][0] = r.x[0][0]; x[0][1] = r.x[0][1]; x[0][2] = r.x[0][2]; x[0][3] = 0; x[1][0] = r.x[1][0]; x[1][1] = r.x[1][1]; x[1][2] = r.x[1][2]; x[1][3] = 0; x[2][0] = r.x[2][0]; x[2][1] = r.x[2][1]; x[2][2] = r.x[2][2]; x[2][3] = 0; x[3][0] = t.x; x[3][1] = t.y; x[3][2] = t.z; x[3][3] = 1; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44 (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44::Matrix44 (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[0][2] = T (v.x[0][2]); x[0][3] = T (v.x[0][3]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); x[1][2] = T (v.x[1][2]); x[1][3] = T (v.x[1][3]); x[2][0] = T (v.x[2][0]); x[2][1] = T (v.x[2][1]); x[2][2] = T (v.x[2][2]); x[2][3] = T (v.x[2][3]); x[3][0] = T (v.x[3][0]); x[3][1] = T (v.x[3][1]); x[3][2] = T (v.x[3][2]); x[3][3] = T (v.x[3][3]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator= (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[0][3] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[1][3] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; x[2][3] = a; x[3][0] = a; x[3][1] = a; x[3][2] = a; x[3][3] = a; return *this; } template IMATH_HOSTDEVICE IMATH_HOSTDEVICE inline T* Matrix44::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template IMATH_HOSTDEVICE inline const T* Matrix44::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template template IMATH_HOSTDEVICE inline void Matrix44::getValue (Matrix44& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[0][2] = x[0][2]; v.x[0][3] = x[0][3]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; v.x[1][2] = x[1][2]; v.x[1][3] = x[1][3]; v.x[2][0] = x[2][0]; v.x[2][1] = x[2][1]; v.x[2][2] = x[2][2]; v.x[2][3] = x[2][3]; v.x[3][0] = x[3][0]; v.x[3][1] = x[3][1]; v.x[3][2] = x[3][2]; v.x[3][3] = x[3][3]; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44& Matrix44::setValue (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = T(v.x[0][0]); x[0][1] = T(v.x[0][1]); x[0][2] = T(v.x[0][2]); x[0][3] = T(v.x[0][3]); x[1][0] = T(v.x[1][0]); x[1][1] = T(v.x[1][1]); x[1][2] = T(v.x[1][2]); x[1][3] = T(v.x[1][3]); x[2][0] = T(v.x[2][0]); x[2][1] = T(v.x[2][1]); x[2][2] = T(v.x[2][2]); x[2][3] = T(v.x[2][3]); x[3][0] = T(v.x[3][0]); x[3][1] = T(v.x[3][1]); x[3][2] = T(v.x[3][2]); x[3][3] = T(v.x[3][3]); return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44& Matrix44::setTheMatrix (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; return *this; } template IMATH_HOSTDEVICE inline void Matrix44::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; } template IMATH_HOSTDEVICE constexpr inline bool Matrix44::operator== (const Matrix44& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[0][2] == v.x[0][2] && x[0][3] == v.x[0][3] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1] && x[1][2] == v.x[1][2] && x[1][3] == v.x[1][3] && x[2][0] == v.x[2][0] && x[2][1] == v.x[2][1] && x[2][2] == v.x[2][2] && x[2][3] == v.x[2][3] && x[3][0] == v.x[3][0] && x[3][1] == v.x[3][1] && x[3][2] == v.x[3][2] && x[3][3] == v.x[3][3]; } template IMATH_HOSTDEVICE constexpr inline bool Matrix44::operator!= (const Matrix44& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[0][2] != v.x[0][2] || x[0][3] != v.x[0][3] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1] || x[1][2] != v.x[1][2] || x[1][3] != v.x[1][3] || x[2][0] != v.x[2][0] || x[2][1] != v.x[2][1] || x[2][2] != v.x[2][2] || x[2][3] != v.x[2][3] || x[3][0] != v.x[3][0] || x[3][1] != v.x[3][1] || x[3][2] != v.x[3][2] || x[3][3] != v.x[3][3]; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix44::equalWithAbsError (const Matrix44& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this).x[i][j], m.x[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Matrix44::equalWithRelError (const Matrix44& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this).x[i][j], m.x[i][j], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator+= (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[0][2] += v.x[0][2]; x[0][3] += v.x[0][3]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; x[1][2] += v.x[1][2]; x[1][3] += v.x[1][3]; x[2][0] += v.x[2][0]; x[2][1] += v.x[2][1]; x[2][2] += v.x[2][2]; x[2][3] += v.x[2][3]; x[3][0] += v.x[3][0]; x[3][1] += v.x[3][1]; x[3][2] += v.x[3][2]; x[3][3] += v.x[3][3]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[0][2] += a; x[0][3] += a; x[1][0] += a; x[1][1] += a; x[1][2] += a; x[1][3] += a; x[2][0] += a; x[2][1] += a; x[2][2] += a; x[2][3] += a; x[3][0] += a; x[3][1] += a; x[3][2] += a; x[3][3] += a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::operator+ (const Matrix44& v) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[0][2] + v.x[0][2], x[0][3] + v.x[0][3], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1], x[1][2] + v.x[1][2], x[1][3] + v.x[1][3], x[2][0] + v.x[2][0], x[2][1] + v.x[2][1], x[2][2] + v.x[2][2], x[2][3] + v.x[2][3], x[3][0] + v.x[3][0], x[3][1] + v.x[3][1], x[3][2] + v.x[3][2], x[3][3] + v.x[3][3]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator-= (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[0][2] -= v.x[0][2]; x[0][3] -= v.x[0][3]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; x[1][2] -= v.x[1][2]; x[1][3] -= v.x[1][3]; x[2][0] -= v.x[2][0]; x[2][1] -= v.x[2][1]; x[2][2] -= v.x[2][2]; x[2][3] -= v.x[2][3]; x[3][0] -= v.x[3][0]; x[3][1] -= v.x[3][1]; x[3][2] -= v.x[3][2]; x[3][3] -= v.x[3][3]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[0][2] -= a; x[0][3] -= a; x[1][0] -= a; x[1][1] -= a; x[1][2] -= a; x[1][3] -= a; x[2][0] -= a; x[2][1] -= a; x[2][2] -= a; x[2][3] -= a; x[3][0] -= a; x[3][1] -= a; x[3][2] -= a; x[3][3] -= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::operator- (const Matrix44& v) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[0][2] - v.x[0][2], x[0][3] - v.x[0][3], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1], x[1][2] - v.x[1][2], x[1][3] - v.x[1][3], x[2][0] - v.x[2][0], x[2][1] - v.x[2][1], x[2][2] - v.x[2][2], x[2][3] - v.x[2][3], x[3][0] - v.x[3][0], x[3][1] - v.x[3][1], x[3][2] - v.x[3][2], x[3][3] - v.x[3][3]); } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::operator-() const IMATH_NOEXCEPT { return Matrix44 (-x[0][0], -x[0][1], -x[0][2], -x[0][3], -x[1][0], -x[1][1], -x[1][2], -x[1][3], -x[2][0], -x[2][1], -x[2][2], -x[2][3], -x[3][0], -x[3][1], -x[3][2], -x[3][3]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[0][2] = -x[0][2]; x[0][3] = -x[0][3]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; x[1][2] = -x[1][2]; x[1][3] = -x[1][3]; x[2][0] = -x[2][0]; x[2][1] = -x[2][1]; x[2][2] = -x[2][2]; x[2][3] = -x[2][3]; x[3][0] = -x[3][0]; x[3][1] = -x[3][1]; x[3][2] = -x[3][2]; x[3][3] = -x[3][3]; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[0][2] *= a; x[0][3] *= a; x[1][0] *= a; x[1][1] *= a; x[1][2] *= a; x[1][3] *= a; x[2][0] *= a; x[2][1] *= a; x[2][2] *= a; x[2][3] *= a; x[3][0] *= a; x[3][1] *= a; x[3][2] *= a; x[3][3] *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::operator* (T a) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] * a, x[0][1] * a, x[0][2] * a, x[0][3] * a, x[1][0] * a, x[1][1] * a, x[1][2] * a, x[1][3] * a, x[2][0] * a, x[2][1] * a, x[2][2] * a, x[2][3] * a, x[3][0] * a, x[3][1] * a, x[3][2] * a, x[3][3] * a); } /// Matrix-scalar multiplication template IMATH_HOSTDEVICE inline Matrix44 operator* (T a, const Matrix44& v) IMATH_NOEXCEPT { return v * a; } template IMATH_HOSTDEVICE inline IMATH_CONSTEXPR14 Matrix44 Matrix44::multiply (const Matrix44 &a, const Matrix44 &b) IMATH_NOEXCEPT { const auto a00 = a.x[0][0]; const auto a01 = a.x[0][1]; const auto a02 = a.x[0][2]; const auto a03 = a.x[0][3]; const auto c00 = a00 * b.x[0][0] + a01 * b.x[1][0] + a02 * b.x[2][0] + a03 * b.x[3][0]; const auto c01 = a00 * b.x[0][1] + a01 * b.x[1][1] + a02 * b.x[2][1] + a03 * b.x[3][1]; const auto c02 = a00 * b.x[0][2] + a01 * b.x[1][2] + a02 * b.x[2][2] + a03 * b.x[3][2]; const auto c03 = a00 * b.x[0][3] + a01 * b.x[1][3] + a02 * b.x[2][3] + a03 * b.x[3][3]; const auto a10 = a.x[1][0]; const auto a11 = a.x[1][1]; const auto a12 = a.x[1][2]; const auto a13 = a.x[1][3]; const auto c10 = a10 * b.x[0][0] + a11 * b.x[1][0] + a12 * b.x[2][0] + a13 * b.x[3][0]; const auto c11 = a10 * b.x[0][1] + a11 * b.x[1][1] + a12 * b.x[2][1] + a13 * b.x[3][1]; const auto c12 = a10 * b.x[0][2] + a11 * b.x[1][2] + a12 * b.x[2][2] + a13 * b.x[3][2]; const auto c13 = a10 * b.x[0][3] + a11 * b.x[1][3] + a12 * b.x[2][3] + a13 * b.x[3][3]; const auto a20 = a.x[2][0]; const auto a21 = a.x[2][1]; const auto a22 = a.x[2][2]; const auto a23 = a.x[2][3]; const auto c20 = a20 * b.x[0][0] + a21 * b.x[1][0] + a22 * b.x[2][0] + a23 * b.x[3][0]; const auto c21 = a20 * b.x[0][1] + a21 * b.x[1][1] + a22 * b.x[2][1] + a23 * b.x[3][1]; const auto c22 = a20 * b.x[0][2] + a21 * b.x[1][2] + a22 * b.x[2][2] + a23 * b.x[3][2]; const auto c23 = a20 * b.x[0][3] + a21 * b.x[1][3] + a22 * b.x[2][3] + a23 * b.x[3][3]; const auto a30 = a.x[3][0]; const auto a31 = a.x[3][1]; const auto a32 = a.x[3][2]; const auto a33 = a.x[3][3]; const auto c30 = a30 * b.x[0][0] + a31 * b.x[1][0] + a32 * b.x[2][0] + a33 * b.x[3][0]; const auto c31 = a30 * b.x[0][1] + a31 * b.x[1][1] + a32 * b.x[2][1] + a33 * b.x[3][1]; const auto c32 = a30 * b.x[0][2] + a31 * b.x[1][2] + a32 * b.x[2][2] + a33 * b.x[3][2]; const auto c33 = a30 * b.x[0][3] + a31 * b.x[1][3] + a32 * b.x[2][3] + a33 * b.x[3][3]; return Matrix44(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator*= (const Matrix44& v) IMATH_NOEXCEPT { *this = multiply(*this, v); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44 Matrix44::operator* (const Matrix44& v) const IMATH_NOEXCEPT { return multiply(*this, v); } template IMATH_HOSTDEVICE inline void Matrix44::multiply (const Matrix44& a, const Matrix44& b, Matrix44& c) IMATH_NOEXCEPT { c = multiply(a, b); } template template IMATH_HOSTDEVICE inline void Matrix44::multVecMatrix (const Vec3& src, Vec3& dst) const IMATH_NOEXCEPT { S a, b, c, w; a = src.x * x[0][0] + src.y * x[1][0] + src.z * x[2][0] + x[3][0]; b = src.x * x[0][1] + src.y * x[1][1] + src.z * x[2][1] + x[3][1]; c = src.x * x[0][2] + src.y * x[1][2] + src.z * x[2][2] + x[3][2]; w = src.x * x[0][3] + src.y * x[1][3] + src.z * x[2][3] + x[3][3]; dst.x = a / w; dst.y = b / w; dst.z = c / w; } template template IMATH_HOSTDEVICE inline void Matrix44::multDirMatrix (const Vec3& src, Vec3& dst) const IMATH_NOEXCEPT { S a, b, c; a = src.x * x[0][0] + src.y * x[1][0] + src.z * x[2][0]; b = src.x * x[0][1] + src.y * x[1][1] + src.z * x[2][1]; c = src.x * x[0][2] + src.y * x[1][2] + src.z * x[2][2]; dst.x = a; dst.y = b; dst.z = c; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[0][2] /= a; x[0][3] /= a; x[1][0] /= a; x[1][1] /= a; x[1][2] /= a; x[1][3] /= a; x[2][0] /= a; x[2][1] /= a; x[2][2] /= a; x[2][3] /= a; x[3][0] /= a; x[3][1] /= a; x[3][2] /= a; x[3][3] /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::operator/ (T a) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] / a, x[0][1] / a, x[0][2] / a, x[0][3] / a, x[1][0] / a, x[1][1] / a, x[1][2] / a, x[1][3] / a, x[2][0] / a, x[2][1] / a, x[2][2] / a, x[2][3] / a, x[3][0] / a, x[3][1] / a, x[3][2] / a, x[3][3] / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::transpose() IMATH_NOEXCEPT { Matrix44 tmp (x[0][0], x[1][0], x[2][0], x[3][0], x[0][1], x[1][1], x[2][1], x[3][1], x[0][2], x[1][2], x[2][2], x[3][2], x[0][3], x[1][3], x[2][3], x[3][3]); *this = tmp; return *this; } template IMATH_HOSTDEVICE constexpr inline Matrix44 Matrix44::transposed() const IMATH_NOEXCEPT { return Matrix44 (x[0][0], x[1][0], x[2][0], x[3][0], x[0][1], x[1][1], x[2][1], x[3][1], x[0][2], x[1][2], x[2][2], x[3][2], x[0][3], x[1][3], x[2][3], x[3][3]); } template IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::gjInvert() IMATH_NOEXCEPT { *this = gjInverse(); return *this; } template inline Matrix44 Matrix44::gjInverse (bool singExc) const { int i, j, k; Matrix44 s; Matrix44 t (*this); // Forward elimination for (i = 0; i < 3; i++) { int pivot = i; T pivotsize = t.x[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 4; j++) { T tmp = t.x[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } if (pivot != i) { for (j = 0; j < 4; j++) { T tmp; tmp = t.x[i][j]; t.x[i][j] = t.x[pivot][j]; t.x[pivot][j] = tmp; tmp = s.x[i][j]; s.x[i][j] = s.x[pivot][j]; s.x[pivot][j] = tmp; } } for (j = i + 1; j < 4; j++) { T f = t.x[j][i] / t.x[i][i]; for (k = 0; k < 4; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } // Backward substitution for (i = 3; i >= 0; --i) { T f; if ((f = t.x[i][i]) == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } for (j = 0; j < 4; j++) { t.x[i][j] /= f; s.x[i][j] /= f; } for (j = 0; j < i; j++) { f = t.x[j][i]; for (k = 0; k < 4; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } return s; } template IMATH_HOSTDEVICE inline Matrix44 Matrix44::gjInverse() const IMATH_NOEXCEPT { int i, j, k; Matrix44 s; Matrix44 t (*this); // Forward elimination for (i = 0; i < 3; i++) { int pivot = i; T pivotsize = t.x[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 4; j++) { T tmp = t.x[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { return Matrix44(); } if (pivot != i) { for (j = 0; j < 4; j++) { T tmp; tmp = t.x[i][j]; t.x[i][j] = t.x[pivot][j]; t.x[pivot][j] = tmp; tmp = s.x[i][j]; s.x[i][j] = s.x[pivot][j]; s.x[pivot][j] = tmp; } } for (j = i + 1; j < 4; j++) { T f = t.x[j][i] / t.x[i][i]; for (k = 0; k < 4; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } // Backward substitution for (i = 3; i >= 0; --i) { T f; if ((f = t.x[i][i]) == 0) { return Matrix44(); } for (j = 0; j < 4; j++) { t.x[i][j] /= f; s.x[i][j] /= f; } for (j = 0; j < i; j++) { f = t.x[j][i]; for (k = 0; k < 4; k++) { t.x[j][k] -= f * t.x[i][k]; s.x[j][k] -= f * s.x[i][k]; } } } return s; } template IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::invert (bool singExc) { *this = inverse (singExc); return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template IMATH_CONSTEXPR14 inline Matrix44 Matrix44::inverse (bool singExc) const { if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) return gjInverse (singExc); Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], 0, x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], 0, x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1], 0, 0, 0, 0, 1); T r = x[0][0] * s.x[0][0] + x[0][1] * s.x[1][0] + x[0][2] * s.x[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } } } } s.x[3][0] = -x[3][0] * s.x[0][0] - x[3][1] * s.x[1][0] - x[3][2] * s.x[2][0]; s.x[3][1] = -x[3][0] * s.x[0][1] - x[3][1] * s.x[1][1] - x[3][2] * s.x[2][1]; s.x[3][2] = -x[3][0] * s.x[0][2] - x[3][1] * s.x[1][2] - x[3][2] * s.x[2][2]; return s; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Matrix44 Matrix44::inverse() const IMATH_NOEXCEPT { if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) return gjInverse(); Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], 0, x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], 0, x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1], 0, 0, 0, 0, 1); T r = x[0][0] * s.x[0][0] + x[0][1] * s.x[1][0] + x[0][2] * s.x[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s.x[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s.x[i][j])) { s.x[i][j] /= r; } else { return Matrix44(); } } } } s.x[3][0] = -x[3][0] * s.x[0][0] - x[3][1] * s.x[1][0] - x[3][2] * s.x[2][0]; s.x[3][1] = -x[3][0] * s.x[0][1] - x[3][1] * s.x[1][1] - x[3][2] * s.x[2][1]; s.x[3][2] = -x[3][0] * s.x[0][2] - x[3][1] * s.x[1][2] - x[3][2] * s.x[2][2]; return s; } template IMATH_HOSTDEVICE constexpr inline T Matrix44::fastMinor (const int r0, const int r1, const int r2, const int c0, const int c1, const int c2) const IMATH_NOEXCEPT { return x[r0][c0] * (x[r1][c1] * x[r2][c2] - x[r1][c2] * x[r2][c1]) + x[r0][c1] * (x[r1][c2] * x[r2][c0] - x[r1][c0] * x[r2][c2]) + x[r0][c2] * (x[r1][c0] * x[r2][c1] - x[r1][c1] * x[r2][c0]); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Matrix44::minorOf (const int r, const int c) const IMATH_NOEXCEPT { int r0 = 0 + (r < 1 ? 1 : 0); int r1 = 1 + (r < 2 ? 1 : 0); int r2 = 2 + (r < 3 ? 1 : 0); int c0 = 0 + (c < 1 ? 1 : 0); int c1 = 1 + (c < 2 ? 1 : 0); int c2 = 2 + (c < 3 ? 1 : 0); Matrix33 working (x[r0][c0], x[r1][c0], x[r2][c0], x[r0][c1], x[r1][c1], x[r2][c1], x[r0][c2], x[r1][c2], x[r2][c2]); return working.determinant(); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Matrix44::determinant() const IMATH_NOEXCEPT { T sum = (T) 0; if (x[0][3] != 0.) sum -= x[0][3] * fastMinor (1, 2, 3, 0, 1, 2); if (x[1][3] != 0.) sum += x[1][3] * fastMinor (0, 2, 3, 0, 1, 2); if (x[2][3] != 0.) sum -= x[2][3] * fastMinor (0, 1, 3, 0, 1, 2); if (x[3][3] != 0.) sum += x[3][3] * fastMinor (0, 1, 2, 0, 1, 2); return sum; } template template IMATH_HOSTDEVICE inline const Matrix44& Matrix44::setEulerAngles (const Vec3& r) IMATH_NOEXCEPT { S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; cos_rz = cos ((T) r.z); cos_ry = cos ((T) r.y); cos_rx = cos ((T) r.x); sin_rz = sin ((T) r.z); sin_ry = sin ((T) r.y); sin_rx = sin ((T) r.x); x[0][0] = cos_rz * cos_ry; x[0][1] = sin_rz * cos_ry; x[0][2] = -sin_ry; x[0][3] = 0; x[1][0] = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; x[1][1] = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; x[1][2] = cos_ry * sin_rx; x[1][3] = 0; x[2][0] = sin_rz * sin_rx + cos_rz * sin_ry * cos_rx; x[2][1] = -cos_rz * sin_rx + sin_rz * sin_ry * cos_rx; x[2][2] = cos_ry * cos_rx; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setAxisAngle (const Vec3& axis, S angle) IMATH_NOEXCEPT { Vec3 unit (axis.normalized()); S sine = std::sin (angle); S cosine = std::cos (angle); x[0][0] = unit.x * unit.x * (1 - cosine) + cosine; x[0][1] = unit.x * unit.y * (1 - cosine) + unit.z * sine; x[0][2] = unit.x * unit.z * (1 - cosine) - unit.y * sine; x[0][3] = 0; x[1][0] = unit.x * unit.y * (1 - cosine) - unit.z * sine; x[1][1] = unit.y * unit.y * (1 - cosine) + cosine; x[1][2] = unit.y * unit.z * (1 - cosine) + unit.x * sine; x[1][3] = 0; x[2][0] = unit.x * unit.z * (1 - cosine) + unit.y * sine; x[2][1] = unit.y * unit.z * (1 - cosine) - unit.x * sine; x[2][2] = unit.z * unit.z * (1 - cosine) + cosine; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE inline const Matrix44& Matrix44::rotate (const Vec3& r) IMATH_NOEXCEPT { S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; S m00, m01, m02; S m10, m11, m12; S m20, m21, m22; cos_rz = cos ((S) r.z); cos_ry = cos ((S) r.y); cos_rx = cos ((S) r.x); sin_rz = sin ((S) r.z); sin_ry = sin ((S) r.y); sin_rx = sin ((S) r.x); m00 = cos_rz * cos_ry; m01 = sin_rz * cos_ry; m02 = -sin_ry; m10 = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; m11 = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; m12 = cos_ry * sin_rx; m20 = -sin_rz * -sin_rx + cos_rz * sin_ry * cos_rx; m21 = cos_rz * -sin_rx + sin_rz * sin_ry * cos_rx; m22 = cos_ry * cos_rx; Matrix44 P (*this); x[0][0] = P.x[0][0] * m00 + P.x[1][0] * m01 + P.x[2][0] * m02; x[0][1] = P.x[0][1] * m00 + P.x[1][1] * m01 + P.x[2][1] * m02; x[0][2] = P.x[0][2] * m00 + P.x[1][2] * m01 + P.x[2][2] * m02; x[0][3] = P.x[0][3] * m00 + P.x[1][3] * m01 + P.x[2][3] * m02; x[1][0] = P.x[0][0] * m10 + P.x[1][0] * m11 + P.x[2][0] * m12; x[1][1] = P.x[0][1] * m10 + P.x[1][1] * m11 + P.x[2][1] * m12; x[1][2] = P.x[0][2] * m10 + P.x[1][2] * m11 + P.x[2][2] * m12; x[1][3] = P.x[0][3] * m10 + P.x[1][3] * m11 + P.x[2][3] * m12; x[2][0] = P.x[0][0] * m20 + P.x[1][0] * m21 + P.x[2][0] * m22; x[2][1] = P.x[0][1] * m20 + P.x[1][1] * m21 + P.x[2][1] * m22; x[2][2] = P.x[0][2] * m20 + P.x[1][2] * m21 + P.x[2][2] * m22; x[2][3] = P.x[0][3] * m20 + P.x[1][3] * m21 + P.x[2][3] * m22; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to a 3D homogeneous transform scale: // | s 0 0 0 | // | 0 s 0 0 | // | 0 0 s 0 | // | 0 0 0 1 | // x[0][0] = s; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = s; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = s; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setScale (const Vec3& s) IMATH_NOEXCEPT { // // Set the matrix to a 3D homogeneous transform scale: // | s.x 0 0 0 | // | 0 s.y 0 0 | // | 0 0 s.z 0 | // | 0 0 0 1 | // x[0][0] = s.x; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = s.y; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = s.z; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::scale (const Vec3& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[0][2] *= s.x; x[0][3] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; x[1][2] *= s.y; x[1][3] *= s.y; x[2][0] *= s.z; x[2][1] *= s.z; x[2][2] *= s.z; x[2][3] *= s.z; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setTranslation (const Vec3& t) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = t.x; x[3][1] = t.y; x[3][2] = t.z; x[3][3] = 1; return *this; } template IMATH_HOSTDEVICE constexpr inline const Vec3 Matrix44::translation() const IMATH_NOEXCEPT { return Vec3 (x[3][0], x[3][1], x[3][2]); } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::translate (const Vec3& t) IMATH_NOEXCEPT { x[3][0] += t.x * x[0][0] + t.y * x[1][0] + t.z * x[2][0]; x[3][1] += t.x * x[0][1] + t.y * x[1][1] + t.z * x[2][1]; x[3][2] += t.x * x[0][2] + t.y * x[1][2] + t.z * x[2][2]; x[3][3] += t.x * x[0][3] + t.y * x[1][3] + t.z * x[2][3]; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setShear (const Vec3& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = h.x; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = h.y; x[2][1] = h.z; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::setShear (const Shear6& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = h.yx; x[0][2] = h.zx; x[0][3] = 0; x[1][0] = h.xy; x[1][1] = 1; x[1][2] = h.zy; x[1][3] = 0; x[2][0] = h.xz; x[2][1] = h.yz; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::shear (const Vec3& h) IMATH_NOEXCEPT { // // In this case, we don't need a temp. copy of the matrix // because we never use a value on the RHS after we've // changed it on the LHS. // for (int i = 0; i < 4; i++) { x[2][i] += h.y * x[0][i] + h.z * x[1][i]; x[1][i] += h.x * x[0][i]; } return *this; } template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Matrix44& Matrix44::shear (const Shear6& h) IMATH_NOEXCEPT { Matrix44 P (*this); for (int i = 0; i < 4; i++) { x[0][i] = P.x[0][i] + h.yx * P.x[1][i] + h.zx * P.x[2][i]; x[1][i] = h.xy * P.x[0][i] + P.x[1][i] + h.zy * P.x[2][i]; x[2][i] = h.xz * P.x[0][i] + h.yz * P.x[1][i] + P.x[2][i]; } return *this; } //-------------------------------- // Implementation of stream output //-------------------------------- template std::ostream& operator<< (std::ostream& s, const Matrix22& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << ")\n"; s.flags (oldFlags); return s; } template std::ostream& operator<< (std::ostream& s, const Matrix33& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << " " << std::setw (width) << m[0][2] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << " " << std::setw (width) << m[1][2] << "\n" << " " << std::setw (width) << m[2][0] << " " << std::setw (width) << m[2][1] << " " << std::setw (width) << m[2][2] << ")\n"; s.flags (oldFlags); return s; } template std::ostream& operator<< (std::ostream& s, const Matrix44& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << " " << std::setw (width) << m[0][2] << " " << std::setw (width) << m[0][3] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << " " << std::setw (width) << m[1][2] << " " << std::setw (width) << m[1][3] << "\n" << " " << std::setw (width) << m[2][0] << " " << std::setw (width) << m[2][1] << " " << std::setw (width) << m[2][2] << " " << std::setw (width) << m[2][3] << "\n" << " " << std::setw (width) << m[3][0] << " " << std::setw (width) << m[3][1] << " " << std::setw (width) << m[3][2] << " " << std::setw (width) << m[3][3] << ")\n"; s.flags (oldFlags); return s; } //--------------------------------------------------------------- // Implementation of vector-times-matrix multiplication operators //--------------------------------------------------------------- template IMATH_HOSTDEVICE inline const Vec2& operator*= (Vec2& v, const Matrix22& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1]); v.x = x; v.y = y; return v; } template IMATH_HOSTDEVICE inline Vec2 operator* (const Vec2& v, const Matrix22& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1]); return Vec2 (x, y); } template IMATH_HOSTDEVICE inline const Vec2& operator*= (Vec2& v, const Matrix33& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + m.x[2][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + m.x[2][1]); S w = S (v.x * m.x[0][2] + v.y * m.x[1][2] + m.x[2][2]); v.x = x / w; v.y = y / w; return v; } template IMATH_HOSTDEVICE inline Vec2 operator* (const Vec2& v, const Matrix33& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + m.x[2][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + m.x[2][1]); S w = S (v.x * m.x[0][2] + v.y * m.x[1][2] + m.x[2][2]); return Vec2 (x / w, y / w); } template IMATH_HOSTDEVICE inline const Vec3& operator*= (Vec3& v, const Matrix33& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2]); v.x = x; v.y = y; v.z = z; return v; } template IMATH_HOSTDEVICE inline Vec3 operator* (const Vec3& v, const Matrix33& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2]); return Vec3 (x, y, z); } template IMATH_HOSTDEVICE inline const Vec3& operator*= (Vec3& v, const Matrix44& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0] + m.x[3][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1] + m.x[3][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2] + m.x[3][2]); S w = S (v.x * m.x[0][3] + v.y * m.x[1][3] + v.z * m.x[2][3] + m.x[3][3]); v.x = x / w; v.y = y / w; v.z = z / w; return v; } template IMATH_HOSTDEVICE inline Vec3 IMATH_HOSTDEVICE operator* (const Vec3& v, const Matrix44& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0] + m.x[3][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1] + m.x[3][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2] + m.x[3][2]); S w = S (v.x * m.x[0][3] + v.y * m.x[1][3] + v.z * m.x[2][3] + m.x[3][3]); return Vec3 (x / w, y / w, z / w); } template IMATH_HOSTDEVICE inline const Vec4& IMATH_HOSTDEVICE operator*= (Vec4& v, const Matrix44& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0] + v.w * m.x[3][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1] + v.w * m.x[3][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2] + v.w * m.x[3][2]); S w = S (v.x * m.x[0][3] + v.y * m.x[1][3] + v.z * m.x[2][3] + v.w * m.x[3][3]); v.x = x; v.y = y; v.z = z; v.w = w; return v; } template IMATH_HOSTDEVICE inline Vec4 IMATH_HOSTDEVICE operator* (const Vec4& v, const Matrix44& m) IMATH_NOEXCEPT { S x = S (v.x * m.x[0][0] + v.y * m.x[1][0] + v.z * m.x[2][0] + v.w * m.x[3][0]); S y = S (v.x * m.x[0][1] + v.y * m.x[1][1] + v.z * m.x[2][1] + v.w * m.x[3][1]); S z = S (v.x * m.x[0][2] + v.y * m.x[1][2] + v.z * m.x[2][2] + v.w * m.x[3][2]); S w = S (v.x * m.x[0][3] + v.y * m.x[1][3] + v.z * m.x[2][3] + v.w * m.x[3][3]); return Vec4 (x, y, z, w); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHMATRIX_H