1678 lines
37 KiB
C++
1678 lines
37 KiB
C++
/// \file
|
|
/// {COMMON_HEADER}
|
|
///
|
|
/// \section DESCRIPTION
|
|
/// This header file provides may types for working with matrices.
|
|
#ifndef _VN_MATH_MAT_H_
|
|
#define _VN_MATH_MAT_H_
|
|
|
|
#include <cassert>
|
|
#include <iostream>
|
|
|
|
#include "vector.h"
|
|
#include "exceptions.h"
|
|
|
|
namespace vn {
|
|
namespace math {
|
|
|
|
/// \brief Template for a matrix.
|
|
template <size_t m, size_t n = m, typename T = float>
|
|
struct mat
|
|
{
|
|
// Public Members /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief The matrix's elements.
|
|
union
|
|
{
|
|
T e[m * n];
|
|
};
|
|
|
|
// Constructors ///////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Creates a new matrix with uninitialized elements.
|
|
mat() { }
|
|
|
|
/// \brief Creates a new matrix with ints elements initialized to val.
|
|
///
|
|
/// \param[in] val The initialization value.
|
|
explicit mat(T val)
|
|
{
|
|
std::fill_n(e, m * n, val);
|
|
}
|
|
|
|
// Helper Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Matrix with all of its elements set to 0.
|
|
///
|
|
/// \return The 0 matrix.
|
|
static mat zero()
|
|
{
|
|
return mat<m, n, T>(0);
|
|
}
|
|
|
|
/// \brief Matrix with all of its elements set to 1.
|
|
///
|
|
/// \return The 1 matrix.
|
|
static mat one()
|
|
{
|
|
return mat<m, n, T>(1);
|
|
}
|
|
|
|
/// \brief Identity matrix with its diagonal elements set to 1.
|
|
///
|
|
/// \return The identity matrix.
|
|
static mat<m, m, T> identity()
|
|
{
|
|
assert(m == n);
|
|
|
|
mat<m, m, T> nm(0);
|
|
|
|
for (size_t i = 0; i < m; i++)
|
|
nm.e[i * m + i] = 1;
|
|
|
|
return nm;
|
|
}
|
|
|
|
// Operator Overloads /////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
T& operator()(size_t row, size_t col)
|
|
{
|
|
return const_cast<T&>(static_cast<const mat&>(*this)(row, col));
|
|
}
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
const T& operator()(size_t row, size_t col) const
|
|
{
|
|
assert(row < m && col < n);
|
|
|
|
//return e[col * m + row];
|
|
return e[col + row * m];
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat operator-() const
|
|
{
|
|
return neg();
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const S& rhs)
|
|
{
|
|
for (size_t i = 0; i < m*n; i++)
|
|
e[i] *= rhs;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by another matrix
|
|
///
|
|
/// \param[in] rhs The other matrix.
|
|
/// \return The multiplied matrix.
|
|
template<size_t r, size_t s, typename S>
|
|
mat& operator*(const mat<r, s, S>& rhs)
|
|
{
|
|
// columns from the matrix must match rows of the input matrix
|
|
if (m != s)
|
|
{
|
|
return *this;
|
|
}
|
|
|
|
size_t row = 0;
|
|
size_t col = 0;
|
|
size_t cell = 0;
|
|
|
|
mat<r, n, T> return_mat = zero();
|
|
|
|
// Remember, this matrix is stored in column order
|
|
for (size_t row_index = 0; row_index < r; row_index++)
|
|
{
|
|
for (size_t col_index = 0; col_index < n; col_index++)
|
|
{
|
|
|
|
cell = row_index + (col_index * r);
|
|
|
|
for (size_t cell_index = 0; cell_index < m; cell_index++)
|
|
{
|
|
// calculated for the cell in the current row
|
|
row = (col_index * m) + cell_index;
|
|
// calculated for the cell in the current column
|
|
col = (cell_index * r) + row_index;
|
|
return_mat.e[cell] += this->e[row] * rhs.e[col];
|
|
}
|
|
}
|
|
}
|
|
|
|
return return_mat;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The divided matrix.
|
|
template<typename S>
|
|
mat& operator/=(const T & rhs)
|
|
{
|
|
for (size_t i = 0; i < m*n; i++)
|
|
e[i] /= rhs;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side vector.
|
|
/// \return The resulting vector.
|
|
template<typename S>
|
|
mat& operator+=(const mat<m, n, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < m*n; i++)
|
|
e[i] += rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template<typename S>
|
|
mat& operator-=(const mat<m, n, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < m*n; i++)
|
|
e[i] -= rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Public Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief The matrix's row dimension.
|
|
///
|
|
/// \return The matrix's row dimension.
|
|
size_t dimRow() const { return m; }
|
|
|
|
/// \brief The matrix's column dimension.
|
|
///
|
|
/// \return The matrix's column dimension.
|
|
size_t dimCol() const { return n; }
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat neg() const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < m * n; i++)
|
|
nm.e[i] = -e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The multiplied matrix.
|
|
mat mult(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < m*n; i++)
|
|
nm.e[i] = e[i] * scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The divided matrix.
|
|
mat div(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < m*n; i++)
|
|
nm.e[i] = e[i] / scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] toAdd The matrix to add.
|
|
/// \return The resulting matrix.
|
|
mat add(const mat& toAdd) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < m*n; i++)
|
|
nm.e[i] = e[i] + toAdd.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] toSub The matrix to subtract from this.
|
|
/// \return The resulting matrix.
|
|
mat sub(const mat& toSub) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < m*n; i++)
|
|
nm.e[i] = e[i] - toSub.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Transposes the matrix.
|
|
///
|
|
/// \return The computed transpose.
|
|
mat<n, m, T> transpose() const
|
|
{
|
|
mat<n, m, T> nm;
|
|
|
|
for (size_t row = 0; row < m; row++)
|
|
{
|
|
for (size_t col = 0; col < n; col++)
|
|
{
|
|
nm.e[row * n + col] = e[col * m + row];
|
|
}
|
|
}
|
|
|
|
return nm;
|
|
}
|
|
|
|
};
|
|
|
|
// Specializations ////////////////////////////////////////////////////////////
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// Disable warning about 'nonstandard extension used : nameless struct/union'.
|
|
#pragma warning(disable:4201)
|
|
#endif
|
|
|
|
/// \brief 2x2 matrix specialization.
|
|
template <typename T>
|
|
struct mat<2, 2, T>
|
|
{
|
|
|
|
// Public Members /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
/// \brief Element 0,0.
|
|
T e00;
|
|
|
|
/// \brief Element 1,0.
|
|
T e10;
|
|
|
|
/// \brief Element 0,1.
|
|
T e01;
|
|
|
|
/// \brief Element 1,1.
|
|
T e11;
|
|
};
|
|
|
|
/// \brief The matrix's elements.
|
|
T e[2 * 2];
|
|
};
|
|
|
|
// Constructors ///////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Creates a new matrix with uninitialized elements.
|
|
mat() { }
|
|
|
|
/// \brief Creates a new matrix with its elements initialized to val.
|
|
///
|
|
/// \param[in] val The initialization value.
|
|
explicit mat(T val) :
|
|
e00(val), e10(val),
|
|
e01(val), e11(val)
|
|
{ }
|
|
|
|
/// \brief Creates a new matrix with its components initialized to the
|
|
/// provided values.
|
|
///
|
|
/// \param[in] e00v Element 0,0 value.
|
|
/// \param[in] e01v Element 0,1 value.
|
|
/// \param[in] e10v Element 1,0 value.
|
|
/// \param[in] e11v Element 1,1 value.
|
|
mat(T e00v, T e01v,
|
|
T e10v, T e11v) :
|
|
e00(e00v), e10(e10v),
|
|
e01(e01v), e11(e11v)
|
|
{ }
|
|
|
|
/// \brief Constructs a matrix from 4 column vectors.
|
|
///
|
|
/// \param[in] col0 The 0 column vector.
|
|
/// \param[in] col1 The 1 column vector.
|
|
/// \param[in] col2 The 2 column vector.
|
|
/// \param[in] col3 The 3 column vector.
|
|
mat(vec<2, T> col0, vec<2, T> col1) :
|
|
e00(col0.x), e10(col1.x),
|
|
e01(col0.y), e11(col1.y)
|
|
{}
|
|
|
|
// Helper Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Matrix with all of its elements set to 0.
|
|
///
|
|
/// \return The 0 matrix.
|
|
static mat zero()
|
|
{
|
|
return mat<2, 2, T>(0);
|
|
}
|
|
|
|
/// \brief Matrix with all of its elements set to 1.
|
|
///
|
|
/// \return The 1 matrix.
|
|
static mat one()
|
|
{
|
|
return mat<2, 2, T>(1);
|
|
}
|
|
|
|
/// \brief Identity matrix with its diagonal elements set to 1.
|
|
///
|
|
/// \return The identity matrix.
|
|
static mat<2, 2, T> identity()
|
|
{
|
|
return mat<2, 2, T>(
|
|
1, 0,
|
|
0, 1);
|
|
}
|
|
|
|
// Operator Overloads /////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
T& operator()(size_t row, size_t col)
|
|
{
|
|
return const_cast<T&>(static_cast<const mat&>(*this)(row, col));
|
|
}
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
const T& operator()(size_t row, size_t col) const
|
|
{
|
|
assert(row < 2 && col < 2);
|
|
|
|
return e[col * 2 + row];
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat operator-() const
|
|
{
|
|
return neg();
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const S& rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator*= throws a warning when a mat*f is multiplied by a mat*d.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
e[i] *= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by another matrix.
|
|
///
|
|
/// \param[in] rhs The other matrix.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const mat<2, 2, S>& rhs)
|
|
{
|
|
size_t row = 0;
|
|
size_t col = 0;
|
|
size_t cell = 0;
|
|
|
|
mat<2, 2, T> return_mat = zero();
|
|
|
|
// Remember, this matrix is stored in column order
|
|
for (size_t row_index = 0; row_index < 2; row_index++)
|
|
{
|
|
for (size_t col_index = 0; col_index < 2; col_index++)
|
|
{
|
|
cell = row_index + (col_index * 2);
|
|
|
|
for (size_t cell_index = 0; cell_index < 2; cell_index++)
|
|
{
|
|
// calculated for the cell in the current row
|
|
row = row_index + (cell_index * 2);
|
|
// calculated for the cell in the current column
|
|
col = cell_index + (col_index * 2);
|
|
|
|
return_mat.e[cell] += this->e[row] * rhs.e[col];
|
|
}
|
|
}
|
|
}
|
|
|
|
*this = return_mat;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The divided matrix.
|
|
template<typename S>
|
|
mat& operator/=(const S& rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator/= throws a warning when a mat*f is divided by a double.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
e[i] /= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side vector.
|
|
/// \return The resulting vector.
|
|
template<typename S>
|
|
mat& operator+=(const mat<2, 2, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
e[i] += rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template<typename S>
|
|
mat& operator-=(const mat<2, 2, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
e[i] -= rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Public Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief The matrix's row dimension.
|
|
///
|
|
/// \return The matrix's row dimension.
|
|
size_t dimRow() const { return 2; }
|
|
|
|
/// \brief The matrix's column dimension.
|
|
///
|
|
/// \return The matrix's column dimension.
|
|
|
|
size_t dimCol() const { return 2; }
|
|
|
|
template<typename S>
|
|
void copy(const mat<2, 2, S> rhs)
|
|
{
|
|
*this = rhs;
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat neg() const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
nm.e[i] = -e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The multiplied matrix.
|
|
mat mult(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
nm.e[i] = e[i] * scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The divided matrix.
|
|
mat div(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
nm.e[i] = e[i] / scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] toAdd The matrix to add.
|
|
/// \return The resulting matrix.
|
|
mat add(const mat& toAdd) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
nm.e[i] = e[i] + toAdd.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] toSub The matrix to subtract from this.
|
|
/// \return The resulting matrix.
|
|
mat sub(const mat& toSub) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 2 * 2; i++)
|
|
nm.e[i] = e[i] - toSub.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Transposes the matrix.
|
|
///
|
|
/// \return The computed transpose.
|
|
mat<2, 2, T> transpose() const
|
|
{
|
|
mat<2, 2, T> nm;
|
|
|
|
for (size_t row = 0; row < 2; row++)
|
|
{
|
|
for (size_t col = 0; col < 2; col++)
|
|
{
|
|
nm.e[row * 2 + col] = e[col * 2 + row];
|
|
}
|
|
}
|
|
|
|
return nm;
|
|
}
|
|
};
|
|
|
|
/// \brief 3x3 matrix specialization.
|
|
/// \brief matrix is column ordered in memory
|
|
template <typename T>
|
|
struct mat<3, 3, T>
|
|
{
|
|
|
|
// Public Members /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
/// \brief Element 0,0.
|
|
T e00;
|
|
|
|
/// \brief Element 1,0.
|
|
T e10;
|
|
|
|
/// \brief Element 2,0.
|
|
T e20;
|
|
|
|
/// \brief Element 0,1.
|
|
T e01;
|
|
|
|
/// \brief Element 1,1.
|
|
T e11;
|
|
|
|
/// \brief Element 2,1.
|
|
T e21;
|
|
|
|
/// \brief Element 0,2.
|
|
T e02;
|
|
|
|
/// \brief Element 1,2.
|
|
T e12;
|
|
|
|
/// \brief Element 2,2.
|
|
T e22;
|
|
};
|
|
|
|
/// \brief The matrix's elements.
|
|
T e[3 * 3];
|
|
};
|
|
|
|
// Constructors ///////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Creates a new matrix with uninitialized elements.
|
|
mat() { }
|
|
|
|
/// \brief Creates a new matrix with its elements initialized to val.
|
|
///
|
|
/// \param[in] val The initialization value.
|
|
explicit mat(T val) :
|
|
e00(val), e10(val), e20(val),
|
|
e01(val), e11(val), e21(val),
|
|
e02(val), e12(val), e22(val)
|
|
{ }
|
|
|
|
/// \brief Creates a new matrix with its components intialized to the
|
|
/// provided values.
|
|
///
|
|
/// \param[in] e00v Element 0,0 value.
|
|
/// \param[in] e01v Element 0,1 value.
|
|
/// \param[in] e02v Element 0,2 value.
|
|
/// \param[in] e10v Element 1,0 value.
|
|
/// \param[in] e11v Element 1,1 value.
|
|
/// \param[in] e12v Element 1,2 value.
|
|
/// \param[in] e20v Element 2,0 value.
|
|
/// \param[in] e21v Element 2,1 value.
|
|
/// \param[in] e22v Element 2,2 value.
|
|
mat(T e00v, T e01v, T e02v,
|
|
T e10v, T e11v, T e12v,
|
|
T e20v, T e21v, T e22v) :
|
|
e00(e00v), e10(e10v), e20(e20v),
|
|
e01(e01v), e11(e11v), e21(e21v),
|
|
e02(e02v), e12(e12v), e22(e22v)
|
|
|
|
{ }
|
|
|
|
/// \brief Constructs a matrix from 3 column vectors. Vectors are stored in column order
|
|
///
|
|
/// \param[in] col0 The 0 column vector.
|
|
/// \param[in] col1 The 1 column vector.
|
|
/// \param[in] col2 The 2 column vector.
|
|
mat(vec<3, T> col0, vec<3, T> col1, vec<3, T> col2) :
|
|
e00(col0.x), e10(col0.y), e20(col0.z),
|
|
e01(col1.x), e11(col1.y), e21(col1.z),
|
|
e02(col2.x), e12(col2.y), e22(col2.z)
|
|
{
|
|
|
|
}
|
|
|
|
// Helper Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Matrix with all of its elements set to 0.
|
|
///
|
|
/// \return The 0 matrix.
|
|
static mat zero()
|
|
{
|
|
return mat<3, 3, T>(0);
|
|
}
|
|
|
|
/// \brief Matrix with all of its elements set to 1.
|
|
///
|
|
/// \return The 1 matrix.
|
|
static mat one()
|
|
{
|
|
return mat<3, 3, T>(1);
|
|
}
|
|
|
|
/// \brief Identity matrix with its diagonal elements set to 1.
|
|
///
|
|
/// \return The identity matrix.
|
|
static mat<3, 3, T> identity()
|
|
{
|
|
return mat<3, 3, T>(
|
|
1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, 1);
|
|
}
|
|
|
|
// Operator Overloads /////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
T& operator()(size_t row, size_t col)
|
|
{
|
|
return const_cast<T&>(static_cast<const mat&>(*this)(row, col));
|
|
}
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
const T& operator()(size_t row, size_t col) const
|
|
{
|
|
assert(row < 3 && col < 3);
|
|
|
|
return e[col * 3 + row];
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat operator-() const
|
|
{
|
|
return neg();
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const S& rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator*= throws a warning when a mat*f is multiplied by a mat*d.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
e[i] *= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by another matrix.
|
|
///
|
|
/// \param[in] rhs The other matrix.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const mat<3, 3, S>& rhs)
|
|
{
|
|
size_t counter = 0;
|
|
size_t row = 0;
|
|
size_t col = 0;
|
|
size_t cell = 0;
|
|
mat<3, 3, T> return_mat = zero();
|
|
|
|
// Remember, this matrix is stored in column order
|
|
for(size_t row_index = 0; row_index < 3; row_index++)
|
|
{
|
|
for(size_t col_index = 0; col_index < 3; col_index++)
|
|
{
|
|
cell = row_index + (col_index * 3);
|
|
|
|
for (size_t cell_index = 0; cell_index < 3; cell_index++)
|
|
{
|
|
// calculated for the cell in the current row
|
|
row = row_index + (cell_index * 3);
|
|
// calculated for the cell in the current column
|
|
col = cell_index + (col_index * 3);
|
|
|
|
return_mat.e[cell] += this->e[row] * rhs.e[col];
|
|
}
|
|
}
|
|
}
|
|
|
|
// std::copy(return_mat.e[0], return_mat.e[8], this->e[0]);
|
|
// std::copy(return_mat.e, return_mat.e + 7, this->e);
|
|
*this = return_mat;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The divided matrix.
|
|
template<typename S>
|
|
mat& operator/=(const S & rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator/= throws a warning when a mat*f is divided by a double.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
e[i] /= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side vector.
|
|
/// \return The resulting vector.
|
|
template<typename S>
|
|
mat& operator+=(const mat<3, 3, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
e[i] += rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template<typename S>
|
|
mat& operator-=(const mat<3, 3, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
e[i] -= rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Public Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief The matrix's row dimension.
|
|
///
|
|
/// \return The matrix's row dimension.
|
|
size_t dimRow() const { return 3; }
|
|
|
|
/// \brief The matrix's column dimension.
|
|
///
|
|
/// \return The matrix's column dimension.
|
|
size_t dimCol() const { return 3; }
|
|
size_t dimCols() const { return 3; }
|
|
|
|
template<typename S>
|
|
void copy(const mat<3, 3, S>& rhs)
|
|
{
|
|
*this = rhs;
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat neg() const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
nm.e[i] = -e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The multiplied matrix.
|
|
mat mult(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
nm.e[i] = e[i] * scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The divided matrix.
|
|
mat div(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
nm.e[i] = e[i] / scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] toAdd The matrix to add.
|
|
/// \return The resulting matrix.
|
|
mat add(const mat& toAdd) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
nm.e[i] = e[i] + toAdd.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] toSub The matrix to subtract from this.
|
|
/// \return The resulting matrix.
|
|
mat sub(const mat& toSub) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 3 * 3; i++)
|
|
nm.e[i] = e[i] - toSub.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Transposes the matrix.
|
|
///
|
|
/// \return The computed transpose.
|
|
mat<3, 3, T> transpose() const
|
|
{
|
|
mat<3, 3, T> nm;
|
|
|
|
for (size_t row = 0; row < 3; row++)
|
|
{
|
|
for (size_t col = 0; col < 3; col++)
|
|
{
|
|
nm.e[row * 3 + col] = e[col * 3 + row];
|
|
}
|
|
}
|
|
|
|
return nm;
|
|
}
|
|
};
|
|
|
|
/// \brief 4x4 matrix specialization.
|
|
template <typename T>
|
|
struct mat<4, 4, T>
|
|
{
|
|
|
|
// Public Members /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
/// \brief Element 0,0.
|
|
T e00;
|
|
|
|
/// \brief Element 1,0.
|
|
T e10;
|
|
|
|
/// \brief Element 2,0.
|
|
T e20;
|
|
|
|
/// \brief Element 3,0.
|
|
T e30;
|
|
|
|
/// \brief Element 0,1.
|
|
T e01;
|
|
|
|
/// \brief Element 1,1.
|
|
T e11;
|
|
|
|
/// \brief Element 2,1.
|
|
T e21;
|
|
|
|
/// \brief Element 3,1.
|
|
T e31;
|
|
|
|
/// \brief Element 0,2.
|
|
T e02;
|
|
|
|
/// \brief Element 1,2.
|
|
T e12;
|
|
|
|
/// \brief Element 2,2.
|
|
T e22;
|
|
|
|
/// \brief Element 3,2.
|
|
T e32;
|
|
|
|
/// \brief Element 0,3.
|
|
T e03;
|
|
|
|
/// \brief Element 1,3.
|
|
T e13;
|
|
|
|
/// \brief Element 2,3.
|
|
T e23;
|
|
|
|
/// \brief Element 3,3.
|
|
T e33;
|
|
};
|
|
|
|
/// \brief The matrix's elements.
|
|
T e[4*4];
|
|
};
|
|
|
|
// Constructors ///////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Creates a new matrix with uninitialized elements.
|
|
mat() { }
|
|
|
|
/// \brief Creates a new matrix with its elements initialized to val.
|
|
///
|
|
/// \param[in] val The initialization value.
|
|
explicit mat(T val) :
|
|
e00(val), e01(val), e02(val), e03(val),
|
|
e10(val), e11(val), e12(val), e13(val),
|
|
e20(val), e21(val), e22(val), e23(val),
|
|
e30(val), e31(val), e32(val), e33(val)
|
|
{ }
|
|
|
|
/// \brief Creates a new matrix with its components intialized to the
|
|
/// provided values.
|
|
///
|
|
/// \param[in] e00v Element 0,0 value.
|
|
/// \param[in] e01v Element 0,1 value.
|
|
/// \param[in] e02v Element 0,2 value.
|
|
/// \param[in] e03v Element 0,3 value.
|
|
/// \param[in] e10v Element 1,0 value.
|
|
/// \param[in] e11v Element 1,1 value.
|
|
/// \param[in] e12v Element 1,2 value.
|
|
/// \param[in] e13v Element 1,3 value.
|
|
/// \param[in] e20v Element 2,0 value.
|
|
/// \param[in] e21v Element 2,1 value.
|
|
/// \param[in] e22v Element 2,2 value.
|
|
/// \param[in] e23v Element 2,3 value.
|
|
/// \param[in] e30v Element 3,0 value.
|
|
/// \param[in] e31v Element 3,1 value.
|
|
/// \param[in] e32v Element 3,2 value.
|
|
/// \param[in] e33v Element 3,3 value.
|
|
mat(T e00v, T e01v, T e02v, T e03v,
|
|
T e10v, T e11v, T e12v, T e13v,
|
|
T e20v, T e21v, T e22v, T e23v,
|
|
T e30v, T e31v, T e32v, T e33v) :
|
|
e00(e00v), e01(e01v), e02(e02v), e03(e03v),
|
|
e10(e10v), e11(e11v), e12(e12v), e13(e13v),
|
|
e20(e20v), e21(e21v), e22(e22v), e23(e23v),
|
|
e30(e30v), e31(e31v), e32(e32v), e33(e33v)
|
|
{ }
|
|
|
|
/// \brief Constructs a matrix from 4 column vectors.
|
|
///
|
|
/// \param[in] col0 The 0 column vector.
|
|
/// \param[in] col1 The 1 column vector.
|
|
/// \param[in] col2 The 2 column vector.
|
|
/// \param[in] col3 The 3 column vector.
|
|
mat(vec<4, T> col0, vec<4, T> col1, vec<4, T> col2, vec<4, T> col3) :
|
|
e00(col0.x), e10(col1.x), e20(col2.x), e30(col3.x),
|
|
e01(col0.y), e11(col1.y), e21(col2.y), e31(col3.y),
|
|
e02(col0.z), e12(col1.z), e22(col2.z), e32(col3.z),
|
|
e03(col0.w), e13(col1.w), e23(col2.w), e33(col3.w)
|
|
{
|
|
|
|
}
|
|
|
|
// Helper Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Matrix with all of its elements set to 0.
|
|
///
|
|
/// \return The 0 matrix.
|
|
static mat zero()
|
|
{
|
|
return mat<4, 4, T>(0);
|
|
}
|
|
|
|
/// \brief Matrix with all of its elements set to 1.
|
|
///
|
|
/// \return The 1 matrix.
|
|
static mat one()
|
|
{
|
|
return mat<4, 4, T>(1);
|
|
}
|
|
|
|
/// \brief Identity matrix with its diagonal elements set to 1.
|
|
///
|
|
/// \return The identity matrix.
|
|
static mat<4, 4, T> identity()
|
|
{
|
|
return mat<4, 4, T>(1, 0, 0, 0,
|
|
0, 1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1);
|
|
}
|
|
|
|
// Operator Overloads /////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
T& operator()(size_t row, size_t col)
|
|
{
|
|
return const_cast<T&>(static_cast<const mat&>(*this)(row, col));
|
|
}
|
|
|
|
/// \brief Indexing into the matrix's elements.
|
|
///
|
|
/// \param[in] row The 0-based index row.
|
|
/// \param[in] col The 0-based index column.
|
|
/// \return The requested element.
|
|
const T& operator()(size_t row, size_t col) const
|
|
{
|
|
assert(row < 4 && col < 4);
|
|
|
|
return e[col * 4 + row];
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat operator-() const
|
|
{
|
|
return neg();
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const S& rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator*= throws a warning when a mat*f is multiplied by a mat*d.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 4 * 4; i++)
|
|
e[i] *= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by another matrix.
|
|
///
|
|
/// \param[in] rhs The other matrix.
|
|
/// \return The multiplied matrix.
|
|
template<typename S>
|
|
mat& operator*=(const mat<4, 4, S>& rhs)
|
|
{
|
|
size_t row = 0;
|
|
size_t col = 0;
|
|
size_t cell = 0;
|
|
|
|
mat<4, 4, T> return_mat = zero();
|
|
|
|
// Remember, this matrix is stored in column order
|
|
for (size_t row_index = 0; row_index < 4; row_index++)
|
|
{
|
|
for (size_t col_index = 0; col_index < 4; col_index++)
|
|
{
|
|
cell = row_index + (col_index * 4);
|
|
|
|
for (size_t cell_index = 0; cell_index < 4; cell_index++)
|
|
{
|
|
// calculated for the cell in the current row
|
|
row = row_index + (cell_index * 4);
|
|
// calculated for the cell in the current column
|
|
col = cell_index + (col_index * 4);
|
|
|
|
return_mat.e[cell] += this->e[row] * rhs.e[col];
|
|
}
|
|
}
|
|
}
|
|
|
|
*this = return_mat;
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The divided matrix.
|
|
template<typename S>
|
|
mat& operator/=(const S& rhs)
|
|
{
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
|
|
// The operator/= throws a warning when a mat*f is divided by a double.
|
|
#pragma warning(disable:4244)
|
|
#endif
|
|
|
|
for (size_t i = 0; i < 4 * 4; i++)
|
|
e[i] /= rhs;
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side vector.
|
|
/// \return The resulting vector.
|
|
template<typename S>
|
|
mat& operator+=(const mat<4, 4, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
e[i] += rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template<typename S>
|
|
mat& operator-=(const mat<4, 4, S>& rhs)
|
|
{
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
e[i] -= rhs.e[i];
|
|
|
|
return *this;
|
|
}
|
|
|
|
// Public Methods /////////////////////////////////////////////////////////
|
|
|
|
public:
|
|
|
|
/// \brief The matrix's row dimension.
|
|
///
|
|
/// \return The matrix's row dimension.
|
|
size_t dimRow() const { return 4; }
|
|
|
|
/// \brief The matrix's column dimension.
|
|
///
|
|
/// \return The matrix's column dimension.
|
|
size_t dimCol() const { return 4; }
|
|
|
|
template<typename S>
|
|
void copy(const mat<4, 4, S>& rhs)
|
|
{
|
|
*this = rhs;
|
|
}
|
|
|
|
/// \brief Negates the matrix.
|
|
///
|
|
/// \return The negated matrix.
|
|
mat neg() const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 4 * 4; i++)
|
|
nm.e[i] = -e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Multiplies the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The multiplied matrix.
|
|
mat mult(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
nm.e[i] = e[i] * scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
//mat mult(const mat& rhs)
|
|
|
|
/// \brief Divides the matrix by a scalar.
|
|
///
|
|
/// \param[in] scalar The scalar value.
|
|
/// \return The divided matrix.
|
|
mat div(const double& scalar) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
nm.e[i] = e[i] / scalar;
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Adds a matrix to this matrix.
|
|
///
|
|
/// \param[in] toAdd The matrix to add.
|
|
/// \return The resulting matrix.
|
|
mat add(const mat& toAdd) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
nm.e[i] = e[i] + toAdd.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from this matrix.
|
|
///
|
|
/// \param[in] toSub The matrix to subtract from this.
|
|
/// \return The resulting matrix.
|
|
mat sub(const mat& toSub) const
|
|
{
|
|
mat nm;
|
|
|
|
for (size_t i = 0; i < 4*4; i++)
|
|
nm.e[i] = e[i] - toSub.e[i];
|
|
|
|
return nm;
|
|
}
|
|
|
|
/// \brief Transposes the matrix.
|
|
///
|
|
/// \return The computed transpose.
|
|
mat<4, 4, T> transpose() const
|
|
{
|
|
mat<4, 4, T> nm;
|
|
|
|
for (size_t row = 0; row < 4; row++)
|
|
{
|
|
for (size_t col = 0; col < 4; col++)
|
|
{
|
|
nm.e[row * 4 + col] = e[col * 4 + row];
|
|
}
|
|
}
|
|
|
|
return nm;
|
|
}
|
|
};
|
|
|
|
#if defined (_MSC_VER)
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
// Operator Overloads /////////////////////////////////////////////////////////
|
|
|
|
/// \brief Multiplies a matrix by a scalar.
|
|
///
|
|
/// \param[in] lhs The matrix.
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The result.
|
|
template <size_t m, size_t n, typename T, typename S>
|
|
mat<m, n, T> operator*(mat<m, n, T> lhs, const S& rhs)
|
|
{
|
|
lhs *= rhs;
|
|
|
|
return lhs;
|
|
}
|
|
|
|
/// \brief Multiplies a matrix by a scalar.
|
|
///
|
|
/// \param[in] lhs The scalar.
|
|
/// \param[in] rhs The matrix.
|
|
/// \return The result.
|
|
template <size_t m, size_t n, typename T, typename S>
|
|
mat<m, n, T> operator*(const S& lhs, mat<m, n, T> rhs)
|
|
{
|
|
rhs *= lhs;
|
|
|
|
return rhs;
|
|
}
|
|
|
|
/// \brief Multiplies two matrices together.
|
|
///
|
|
/// \param[in] lhs The left-side matrix.
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The result.
|
|
template <size_t m, size_t n, typename T, size_t r, size_t s, typename S>
|
|
mat<m, n, T> operator*(mat<m, n, T>&lhs, const mat<r, s, S>& rhs)
|
|
{
|
|
mat<m, n, T> tmp = lhs;
|
|
tmp *= rhs;
|
|
|
|
return tmp;
|
|
}
|
|
|
|
/// \brief Divides a matrix by a scalar.
|
|
///
|
|
/// \param[in] lhs The matrix.
|
|
/// \param[in] rhs The scalar.
|
|
/// \return The result.
|
|
template <size_t m, size_t n, typename T, typename S>
|
|
mat<m, n, T> operator/(mat<m, n, T> lhs, const S& rhs)
|
|
{
|
|
lhs /= rhs;
|
|
|
|
return lhs;
|
|
}
|
|
|
|
/// \brief Adds two matrices together.
|
|
///
|
|
/// \param[in] lhs The left-side matrix.
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template <size_t m, size_t n, typename T, typename S>
|
|
mat<m, n, T> operator+(mat<m, n, T> lhs, const mat<m, n, S>& rhs)
|
|
{
|
|
lhs += rhs;
|
|
|
|
return lhs;
|
|
}
|
|
|
|
/// \brief Subtracts a matrix from another matrix.
|
|
///
|
|
/// \param[in] lhs The left-side matrix.
|
|
/// \param[in] rhs The right-side matrix.
|
|
/// \return The resulting matrix.
|
|
template <size_t m, size_t n, typename T, typename S>
|
|
mat<m, n, T> operator-(mat<m, n, T> lhs, const mat<m, n, S>& rhs)
|
|
{
|
|
lhs -= rhs;
|
|
|
|
return lhs;
|
|
}
|
|
|
|
// Specific Typedefs //////////////////////////////////////////////////////////
|
|
|
|
/// \brief 2x2 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<2> mat2;
|
|
|
|
/// \brief 3x3 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<3> mat3;
|
|
|
|
/// \brief 4x4 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<4> mat4;
|
|
|
|
/// \brief 2x2 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<2> mat22;
|
|
|
|
/// \brief 3x3 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<3> mat33;
|
|
|
|
/// \brief 4x4 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<4> mat44;
|
|
|
|
/// \brief 2x2 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<2, 2, float> mat2f;
|
|
|
|
/// \brief 3x3 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<3, 3, float> mat3f;
|
|
|
|
/// \brief 4x4 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<4, 4, float> mat4f;
|
|
|
|
/// \brief 2x2 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<2, 2, double> mat2d;
|
|
|
|
/// \brief 3x3 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<3, 3, double> mat3d;
|
|
|
|
/// \brief 4x4 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<4, 4, double> mat4d;
|
|
|
|
/// \brief 2x2 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<2, 2, long double> mat2ld;
|
|
|
|
/// \brief 3x3 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<3, 3, long double> mat3ld;
|
|
|
|
/// \brief 4x4 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<4, 4, long double> mat4ld;
|
|
|
|
/// \brief 2x2 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<2, 2, float> mat22f;
|
|
|
|
/// \brief 3x3 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<3, 3, float> mat33f;
|
|
|
|
/// \brief 4x4 matrix using <c>float</c> as its underlying data type.
|
|
typedef mat<4, 3, float> mat44f;
|
|
|
|
/// \brief 2x2 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<2, 2, double> mat22d;
|
|
|
|
/// \brief 3x3 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<3, 3, double> mat33d;
|
|
|
|
/// \brief 4x4 matrix using <c>double</c> as its underlying data type.
|
|
typedef mat<4, 4, double> mat44d;
|
|
|
|
/// \brief 2x2 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<2, 2, long double> mat22ld;
|
|
|
|
/// \brief 3x3 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<3, 3, long double> mat33ld;
|
|
|
|
/// \brief 4x4 matrix using <c>long double</c> as its underlying data type.
|
|
typedef mat<4, 4, long double> mat44ld;
|
|
|
|
// Common functions for working with matrices.
|
|
|
|
/// \brief Provides a method to generate a representable string from a provided
|
|
/// matrix.
|
|
///
|
|
/// \param[in] m The matrix to convert to string.
|
|
/// \return The string representation.
|
|
template <size_t mDim, size_t nDim, typename T> std::string str(mat<mDim, nDim, T> m)
|
|
{
|
|
std::stringstream ss;
|
|
ss << "[";
|
|
|
|
for (size_t row_index = 0; row_index < m.dimRow(); row_index++)
|
|
{
|
|
ss << "(";
|
|
|
|
for (size_t col_index = 0; col_index < m.dimCol(); col_index++)
|
|
{
|
|
ss << m(row_index, col_index);
|
|
|
|
if (col_index + 1 < m.dimCol())
|
|
ss << "; ";
|
|
}
|
|
|
|
ss << ")";
|
|
}
|
|
|
|
ss << "]";
|
|
|
|
return ss.str();
|
|
}
|
|
|
|
/// \brief Overloads the ostream << operator for easy usage in displaying
|
|
/// matrices.
|
|
///
|
|
/// \param[in] out The ostream being output to.
|
|
/// \param[in] m The matrix to output to ostream.
|
|
/// \return Reference to the current ostream.
|
|
template <size_t mDim, size_t nDim, typename T> std::ostream& operator<<(std::ostream& out, mat<mDim, nDim, T> m)
|
|
{
|
|
out << str(m);
|
|
return out;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|