sm::mat33

A 3x3 matrix class

#include <sm/mat33>

Header file: <sm/mat33>. Test and example code: examples/mat33.cpp tests/mat33_1.cpp

Table of Contents

Summary

A 3x3 matrix class.

Defined as:

namespace sm {
    template <typename F> requires std::is_floating_point_v<F>
    struct mat33 {
        // ...
        std::array<F, 9> mat;

where F must be a floating point type. The data is stored in an std::array in column-major format; the left-most column of the matrix is stored in the first 3 elements of the array.

Create a mat33

Like mat44, mat33 is initialized as an identity matrix by default.

sm::mat33<float> m;
std::cout << "Identity matrix:\n" << m << std::endl;

As for mat44, you can create and assign an initializer list:

sm::mat33<double> m = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << m << std::endl;

Gives:

[ 1 , 4 , 7 ;
  2 , 5 , 8 ;
  3 , 6 , 9 ]

See how the initializer list is placed into the matrix column-by-column.

The list may contain fewer than9 elements:

sm::mat33<double> m = { 1, 2, 3 };
std::cout << m << std::endl;

Gives:

[ 1 , 0 , 0 ;
  2 , 0 , 0 ;
  3 , 0 , 0 ]

The additional elements are all set to 0. This means you can create a null matrix with

sm::mat33<double> m = { 0 };
std::cout << m << std::endl;

Gives:

[ 0 , 0 , 0 ;
  0 , 0 , 0 ;
  0 , 0 , 0 ]

But careful: if you provide an empty brace list, you will cause the default constructor to be called and the matrix will be the identity matrix. If you want a null matrix, use { {} } or {0}:

sm::mat33<double> m1 = {};      // Yields the identity matrix, NOT the null matrix
sm::mat33<double> m2 = { {} };  // Yields a null matrix
sm::mat33<double> m3 = { 0.0 }; // Yields a null matrix

Set data in the mat33

Raw access to the elements

You can set the data manually with an initializer list:

sm::mat33<int> m; // initially set up as identity matrix
m = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
std::cout << "Matrix contains:\n" << m << std::endl;

which outputs:

Matrix contains:
[ 0 , 3 , 6 ;
  1 , 4 , 7 ;
  2 , 5 , 8 ]

You can change individual elements of the matrix with the array access operator:

m[3] = 100;
std::cout << "Matrix updated:\n" << m << std::endl;

The updated matrix is:

Matrix updated:
[ 0 , 100 , 6 ;
  1 , 4 , 7 ;
  2 , 5 , 8 ]

You can reset a mat33 to the identity matrix:

m.setToIdentity();

Access data in a mat33

You can access individual elements:

sm::mat33<float> m = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
std::cout << "Element 0 of matrix m is " << m[0] << std::endl; // 9

You can access a row or column. These are returned as sm::vec objects:

sm::vec<float, 3> zero_row = m.row(0);
std::cout << zero_row << std::endl; // (9, 6, 3)

sm::vec<float, 3> zero_col = m.col(0);
std::cout << zero_col << std::endl; // (9, 8, 7)

You can access a rotation quaternion that represents the rotation encoded in the 3x3 mat33:

sm::mat33<float> m = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
sm::quaternion<float> q = m.rotation();

Matrix operations

You can add, subtract and multiply mat33 instances, and also add, subtract and multiply by scalars

sm::mat33<double> m1;
sm::mat33<double> m2;
sm::mat33<double> m3 = m1 + m2;
sm::mat33<double> m4 = m1 - m2;
sm::mat33<double> m5 = m1 * m2;
m5 += m2;
m4 -= m3;
m4 *= m1;
m4 *= 3;
sm::mat33<double> m6 = m4 - 7.45;

You can obtain the inverse and transposed matrices or carry out these operations in-place:

sm::mat33<float> m;
sm::mat33<float> mi = m.inverse(); // Returns the inverse.
sm::mat33<float> mt = m.transpose();        // Returns transposed matrix

m.inverse_inplace();   // Invert in-place
m.transpose_inplace(); // Transposes the matrix in place

Matrix operations on vectors

You can multiply 3D vectors by a mat33. Multiplication of a vector by a mat33 always yields another three dimensional vector.

You should always use sm::vec<> as the vector type:

sm::mat33<float> m = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
sm::vec<float, 3> v1 = { 0, 1, 0 };
std::cout << "\n" << m << " * " << v1 << " = " << m * v1 << std::endl;

This gives the output:

[ 1 , 4 , 7 ;
  2 , 5 , 8 ;
  3 , 6 , 9 ]
 * (0,1,0) = (4,5,6)

Matrix properties

The determinant, trace, adjugate and cofactor of the matrix are available via these function calls:

sm::mat33<float> m;
float d = m.determinant();
float t = m.trace();
std::array<float, 9> a = m.adjugate();
std::array<float, 9> c = m.cofactor();

The adjugate and cofactor return std::array rather than mat33 as they are usually used internally during a computation of the inverse.