1 #ifndef INCLUDE_AL_MAT_HPP
2 #define INCLUDE_AL_MAT_HPP
48 #include "al/math/al_Vec.hpp"
52 template <
int N,
class T>
66 #define IT(n) for (int i = 0; i < (n); ++i)
69 static struct MatNoInit {
77 template <
int N,
class T>
102 Mat(
const MatNoInit& v) {}
105 Mat(
const T& r1c1,
const T& r1c2,
const T& r2c1,
const T& r2c2) {
106 set(r1c1, r1c2, r2c1, r2c2);
110 Mat(
const T& r1c1,
const T& r1c2,
const T& r1c3,
const T& r2c1,
const T& r2c2,
111 const T& r2c3,
const T& r3c1,
const T& r3c2,
const T& r3c3) {
112 set(r1c1, r1c2, r1c3, r2c1, r2c2, r2c3, r3c1, r3c2, r3c3);
116 Mat(
const T& r1c1,
const T& r1c2,
const T& r1c3,
const T& r1c4,
const T& r2c1,
117 const T& r2c2,
const T& r2c3,
const T& r2c4,
const T& r3c1,
const T& r3c2,
118 const T& r3c3,
const T& r3c4,
const T& r4c1,
const T& r4c2,
const T& r4c3,
120 set(r1c1, r1c2, r1c3, r1c4, r2c1, r2c2, r2c3, r2c4, r3c1, r3c2, r3c3, r3c4,
121 r4c1, r4c2, r4c3, r4c4);
132 double cs = cos(
angle);
133 double sn = sin(
angle);
148 for (
int r = 0; r < N - 1; ++r) m(r, r) = v[r];
149 m(N - 1, N - 1) = T(1);
160 template <
typename... Vals>
162 return scaling(
Vec<(
sizeof...(Vals)), T>(vals...));
170 for (
int r = 0; r < N - 1; ++r) m(r, N - 1) = v[r];
175 template <
typename... Vals>
185 static const Mat&
pun(
const T* src) {
return *(
const Mat*)(src); }
188 static int size() {
return N * N; }
206 const T&
operator()(
int i,
int j)
const {
return (*
this)[j * N + i]; }
219 for (
int j = 0; j < N - 1; ++j) {
220 for (
int i = j + 1; i < N; ++i) {
221 T& a = (*this)(i, j);
222 T& b = (*this)(j, i);
235 for (
int j = 0; j < M; ++j) {
236 for (
int i = 0; i < M; ++i) {
237 res(j, i) = (*this)(j +
row, i +
col);
245 Mat<N - 1, T> res(MAT_NO_INIT);
246 for (
int j = 0, js = 0; j < N - 1; ++j, ++js) {
247 js += int(js ==
row);
248 for (
int i = 0, is = 0; i < N - 1; ++i, ++is) {
249 is += int(is ==
col);
250 res(j, i) = (*this)(js, is);
263 Mat& operator+=(
const Mat& v) {
264 IT(
size()) { (*this)[i] += v[i]; }
267 Mat& operator-=(
const Mat& v) {
268 IT(
size()) { (*this)[i] -= v[i]; }
271 Mat& operator+=(
const T& v) {
272 IT(
size()) { (*this)[i] += v; }
275 Mat& operator-=(
const T& v) {
276 IT(
size()) { (*this)[i] -= v; }
279 Mat& operator*=(
const T& v) {
280 IT(
size()) { (*this)[i] *= v; }
283 Mat& operator/=(
const T& v) {
284 IT(
size()) { (*this)[i] /= v; }
288 Mat operator-()
const {
290 IT(
size()) { r[i] = -(*this)[i]; }
293 Mat operator+(
const Mat& v)
const {
return Mat(*
this) += v; }
294 Mat operator-(
const Mat& v)
const {
return Mat(*
this) -= v; }
295 Mat operator*(
const Mat& v)
const {
return Mat(*
this) *= v; }
296 Mat operator+(
const T& v)
const {
return Mat(*
this) += v; }
297 Mat operator-(
const T& v)
const {
return Mat(*
this) -= v; }
298 Mat operator*(
const T& v)
const {
return Mat(*
this) *= v; }
299 Mat operator/(
const T& v)
const {
return Mat(*
this) /= v; }
306 for (
int j = 0; j < N; ++j) {
308 for (
int i = 0; i < N; ++i) {
309 r(i, j) = a.
row(i).dot(bcol);
319 IT(N) { r[i] = m.
row(i).dot(vCol); }
327 IT(N) { r[i] = vRow.
dot(m.
col(i)); }
333 IT(
size()) { (*this)[i] = v; }
346 IT(
size()) { (*this)[i] = arr[i]; }
357 Mat&
set(
const U* arr,
int numElements,
int matOffset,
int matStride = 1) {
358 IT(numElements) { (*this)[i * matStride + matOffset] = arr[i]; }
363 Mat&
set(
const T& r1c1,
const T& r1c2,
const T& r2c1,
const T& r2c2,
364 int row = 0,
int col = 0) {
371 Mat&
set(
const T& r1c1,
const T& r1c2,
const T& r1c3,
const T& r2c1,
372 const T& r2c2,
const T& r2c3,
const T& r3c1,
const T& r3c2,
373 const T& r3c3,
int row = 0,
int col = 0) {
381 Mat&
set(
const T& r1c1,
const T& r1c2,
const T& r1c3,
const T& r1c4,
382 const T& r2c1,
const T& r2c2,
const T& r2c3,
const T& r2c4,
383 const T& r3c1,
const T& r3c2,
const T& r3c3,
const T& r3c4,
384 const T& r4c1,
const T& r4c2,
const T& r4c3,
const T& r4c4,
385 int row = 0,
int col = 0) {
396 (*this)(
row + 1,
col) = v2;
404 (*this)(
row + 1,
col) = v2;
405 (*this)(
row + 2,
col) = v3;
410 Mat&
setCol4(
const T& v1,
const T& v2,
const T& v3,
const T& v4,
int col = 0,
413 (*this)(
row + 1,
col) = v2;
414 (*this)(
row + 2,
col) = v3;
415 (*this)(
row + 3,
col) = v4;
421 for (
int i = 0; i < N; ++i) (*
this)[i * (N + 1)] = T(1);
423 for (
int i = 0; i < N - 1; ++i) {
424 for (
int j = i + 1; j < N + i + 1; ++j) {
425 (*this)[i * N + j] = T(0);
437 T cofactors[] = {minor, -minor};
439 int sign = (
row ^
col) & 1;
440 return cofactors[sign];
446 for (
int r = 0; r < N; ++r) {
447 for (
int c = 0; c < N; ++c) {
471 double cs = cos(
angle);
472 double sn = sin(
angle);
473 for (
int R = 0; R < N - 1; ++R) {
474 const T& v1 = (*this)(R, dim1);
475 const T& v2 = (*this)(R, dim2);
476 T t = v1 * cs + v2 * sn;
477 (*this)(R, dim2) = v2 * cs - v1 * sn;
478 (*this)(R, dim1) = t;
486 double cs = cos(
angle);
487 double sn = sin(
angle);
488 for (
int C = 0; C < M; ++C) {
489 const T& v1 = (*this)(dim1, C);
490 const T& v2 = (*this)(dim2, C);
491 T t = v1 * cs - v2 * sn;
492 (*this)(dim2, C) = v2 * cs + v1 * sn;
493 (*this)(dim1, C) = t;
506 for (
int C = 0; C < N - 1; ++C) {
507 for (
int R = 0; R < N - 1; ++R) {
508 (*this)(R, C) *= amount[C];
521 template <
typename... Vals>
523 return scale(
Vec<(
sizeof...(Vals)), T>(vals...));
529 for (
int R = 0; R < N - 1; ++R) {
530 for (
int C = 0; C < N - 1; ++C) {
531 (*this)(R, C) *= amount[R];
540 for (
int R = 0; R < N - 1; ++R) {
541 (*this)(R, N - 1) += amount[R];
553 template <
typename... Vals>
559 void print(std::ostream& stream)
const;
567 template <
int N,
class T>
572 template <
int N,
class T>
573 inline Mat<N, T> operator-(
const T& s,
const Mat<N, T>& v) {
577 template <
int N,
class T>
578 inline Mat<N, T> operator*(
const T& s,
const Mat<N, T>& v) {
583 template <
int N,
class T,
class U>
584 inline Vec<N, U> operator*(
const Mat<N, T>& m,
const Vec<N, U>& vCol) {
589 template <
int N,
class T,
class U>
590 inline Vec<N, U> operator*(
const Vec<N, U>& vRow,
const Mat<N, T>& m) {
608 return m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0);
616 return m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
617 m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
618 m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0));
627 template <
int N,
class T>
630 for (
int i = 0; i < N; ++i) {
659 m =
Mat<2, T>(m(1, 1), -m(0, 1), -m(1, 0), m(0, 0)) /= det;
668 template <
int N,
class T>
675 for (
int i = 0; i < N; ++i) {
676 det += m(0, i) * C(0, i);
691 template <
int N,
class T>
693 for (
int R = 0; R < N; ++R) {
694 stream << (R == 0 ?
" {" :
"");
695 for (
int C = 0; C < N; ++C) {
696 stream <<
"% " << double((*
this)(R, C))
697 << ((R != N - 1) || (C != N - 1) ?
", " :
"}");
Fixed-size n-by-n square matrix.
Mat & set(const T &r1c1, const T &r1c2, const T &r1c3, const T &r2c1, const T &r2c2, const T &r2c3, const T &r3c1, const T &r3c2, const T &r3c3, int row=0, int col=0)
Set 3-by-3 (sub)matrix from arguments.
Mat & setCol4(const T &v1, const T &v2, const T &v3, const T &v4, int col=0, int row=0)
Set a (sub)column.
static Vec< N, U > & multiply(Vec< N, U > &r, const Mat &m, const Vec< N, U > &vCol)
Computes product of matrix multiplied by column vector, r = m * vCol.
Mat & set(const U *arr)
Set elements in column-major order from C array.
const T * elems() const
Get read-only pointer to elements.
Mat & set(const U *arr, int numElements, int matOffset, int matStride=1)
Set elements in column-major order from C array.
T & operator()(int i, int j)
Set element at row i, column j.
static Mat scaling(const Vec< N - 1, V > &v)
Get a scaling transform matrix.
static Mat translation(const Vec< N - 1, V > &v)
Get a translation transform matrix.
Mat< N - 1, T > submatrix(int row, int col) const
Returns a submatrix by removing one row and column.
Vec< N, T > diagonal() const
Return diagonal.
static Mat rotation(double angle, int dim1, int dim2)
Get a rotation transform matrix.
Mat(const Mat< N, U > &src)
const T & operator()(int i, int j) const
Get element at row i, column j.
Mat & setIdentity()
Set elements on diagonal to one and all others to zero.
void print(std::ostream &stream) const
Print to file (stream)
Mat & scale(const V &amount)
Scale transformation matrix by uniform amount.
Mat & translate(const V &amount)
Translate transformation matrix by same amount in all directions.
Mat(const T &r1c1, const T &r1c2, const T &r1c3, const T &r2c1, const T &r2c2, const T &r2c3, const T &r3c1, const T &r3c2, const T &r3c3)
3x3 matrix constructor with element initialization
static Mat scaling(Vals... vals)
Get a scaling transform matrix.
Mat & set(const T &r1c1, const T &r1c2, const T &r2c1, const T &r2c2, int row=0, int col=0)
Set 2-by-2 (sub)matrix from arguments.
static Mat identity()
Get identity matrix.
Mat & rotate(double angle, int dim1, int dim2)
Rotate transformation matrix on a local plane (A' = AR)
Mat & transpose()
Transpose elements.
Vec< N, T > row(int i) const
Return row i as vector.
T & operator[](int i)
Set element at index with no bounds checking.
Mat(const T &r1c1, const T &r1c2, const T &r2c1, const T &r2c2)
2x2 matrix constructor with element initialization
static int size()
Returns total number of elements.
static Mat & pun(T *src)
Returns C array type punned into a matrix.
Mat & setCol3(const T &v1, const T &v2, const T &v3, int col=0, int row=0)
Set a (sub)column.
Mat & set(const T &r1c1, const T &r1c2, const T &r1c3, const T &r1c4, const T &r2c1, const T &r2c2, const T &r2c3, const T &r2c4, const T &r3c1, const T &r3c2, const T &r3c3, const T &r3c4, const T &r4c1, const T &r4c2, const T &r4c3, const T &r4c4, int row=0, int col=0)
Set 4-by-4 (sub)matrix from arguments.
static Mat & multiply(Mat &r, const Mat &a, const Mat &b)
Computes matrix product r = a * b.
Mat & setCol2(const T &v1, const T &v2, int col=0, int row=0)
Set a (sub)column.
Mat & scale(const Vec< N - 1, V > &amount)
Scale transformation matrix.
Mat< M, T > sub(int row=0, int col=0) const
Get an MxM submatrix.
Mat & rotateGlobal(double angle, int dim1, int dim2)
Rotate submatrix on a global plane (A' = RA)
Mat(const T &r1c1, const T &r1c2, const T &r1c3, const T &r1c4, const T &r2c1, const T &r2c2, const T &r2c3, const T &r2c4, const T &r3c1, const T &r3c2, const T &r3c3, const T &r3c4, const T &r4c1, const T &r4c2, const T &r4c3, const T &r4c4)
4x4 matrix constructor with element initialization
static Mat translation(Vals... vals)
Get a translation transform matrix.
const T & operator[](int i) const
Get element at index with no bounds checking.
Vec< N, T > col(int i) const
Return column i as vector.
static Vec< N, U > & multiply(Vec< N, U > &r, const Vec< N, U > &vRow, const Mat &m)
Computes product of row vector multiplied by matrix, r = vRow * m.
T * elems()
Get read-write pointer to elements.
Mat()
Default constructor that initializes elements to zero.
Mat & set(const T &v)
Set all elements to value.
Mat & scale(Vals... vals)
Scale transformation matrix.
Mat & set(const Mat< N, U > &v)
Set elements from another matrix.
Mat(const MatNoInit &v)
Construct without initializing elements.
Mat & translate(const Vec< N - 1, V > &amount)
Translate transformation matrix.
Vec< N *N, T > & vec()
Return matrix punned as a vector.
T trace() const
Get trace (sum of diagonal elements)
Mat< N, T > cofactorMatrix() const
Get cofactor matrix.
Mat & translate(Vals... vals)
Translate transformation matrix.
T cofactor(int row, int col) const
Get cofactor.
T mElems[N *N]
Column-major array of elements.
static Mat scaling(V v)
Get a scaling transform matrix.
Mat & scaleGlobal(const Vec< N - 1, V > &amount)
Scale transformation matrix global coordinates.
Mat & rotateGlobal(double angle, int dim1, int dim2)
Rotate transformation matrix on a global plane (A' = RA)
T dot(const Vec< N, U > &v) const
Returns dot (inner) product between vectors.
bool invert(Mat< 1, T > &m)
Mat< 4, int > Mat4i
integer 4x4 matrix
Mat< 3, float > Mat3f
float 3x3 matrix
Mat< 3, int > Mat3i
integer 3x3 matrix
T angle(const Vec< N, T > &a, const Vec< N, T > &b)
Returns angle, in interval [0, pi], between two vectors.
Mat< 2, double > Mat2d
double 2x2 matrix
Mat< 2, int > Mat2i
integer 2x2 matrix
Mat< 4, double > Mat4d
double 4x4 matrix
Mat< 3, double > Mat3d
double 3x3 matrix
Mat< 2, float > Mat2f
float 2x2 matrix
T determinant(const Mat< 1, T > &m)
Mat< 4, float > Mat4f
float 4x4 matrix