matrix: parameterise on rows+cols+type

This commit is contained in:
Danny Robson 2017-02-21 21:19:28 +11:00
parent 7786d32ba5
commit a56d1e339a
6 changed files with 319 additions and 342 deletions

View File

@ -23,41 +23,13 @@
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
using namespace util; using util::matrix;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>&
matrix<S,T>::transposed (void) const matrix<Rows,Cols,T>::invert (void)
{
matrix<S,T> m;
for (size_t i = 0; i < S; ++i)
for (size_t j = 0; j < S; ++j)
m.values[i][j] = values[j][i];
return m;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
matrix<S,T>&
matrix<S,T>::transpose (void)
{
for (size_t i = 0; i < S; ++i)
for (size_t j = i + 1; j < S; ++j)
std::swap (values[i][j], values[j][i]);
return *this;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
matrix<S,T>&
matrix<S,T>::invert (void)
{ {
return *this = inverse (); return *this = inverse ();
} }
@ -113,32 +85,32 @@ matrix<S,T>::invert (void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T T
util::matrix<S,T>::determinant (void) const util::matrix<Rows,Cols,T>::determinant (void) const
{ {
return util::determinant (*this); return util::determinant (*this);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
util::matrix<S,T> util::matrix<Rows,Cols,T>
util::matrix<S,T>::inverse (void) const util::matrix<Rows,Cols,T>::inverse (void) const
{ {
return util::inverse (*this); return util::inverse (*this);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Cols,Rows,T>
util::transposed (const matrix<S,T> &m) util::transposed (const matrix<Rows,Cols,T> &m)
{ {
util::matrix<S,T> res; util::matrix<Cols,Rows,T> res;
for (size_t y = 0; y < S; ++y) for (size_t y = 0; y < Rows; ++y)
for (size_t x = 0; x < S; ++x) for (size_t x = 0; x < Cols; ++x)
res[y][x] = m[x][y]; res[y][x] = m[x][y];
return res; return res;
@ -146,47 +118,18 @@ util::transposed (const matrix<S,T> &m)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template matrix3f util::transposed (const matrix3f&); template util::matrix3f util::transposed (const matrix3f&);
template matrix4f util::transposed (const matrix4f&); template util::matrix4f util::transposed (const matrix4f&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> util::vector<Rows,T>
matrix<S,T>::operator* (const matrix<S,T> &rhs) const matrix<Rows,Cols,T>::operator* (const vector<Rows,T> &rhs) const
{ {
matrix<S,T> m; vector<Rows,T> out;
for (unsigned row = 0; row < S; ++row) { for (size_t i = 0; i < Rows; ++i)
for (unsigned col = 0; col < S; ++col) {
m.values[row][col] = T {0};
for (unsigned inner = 0; inner < S; ++inner)
m.values[row][col] += values[row][inner] * rhs.values[inner][col];
}
}
return m;
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
matrix<S,T>&
matrix<S,T>::operator*=(const matrix<S,T> &rhs)
{
return *this = *this * rhs;
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
vector<S,T>
matrix<S,T>::operator* (const vector<S,T> &rhs) const
{
vector<S,T> out;
for (size_t i = 0; i < S; ++i)
out[i] = dot (rhs, values[i]); out[i] = dot (rhs, values[i]);
return out; return out;
@ -194,13 +137,13 @@ matrix<S,T>::operator* (const vector<S,T> &rhs) const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
point<S,T> util::point<Rows,T>
matrix<S,T>::operator* (const point<S,T> &rhs) const matrix<Rows,Cols,T>::operator* (const point<Rows,T> &rhs) const
{ {
point<S,T> out; point<Rows,T> out;
for (size_t i = 0; i < S; ++i) for (size_t i = 0; i < Rows; ++i)
out[i] = dot (rhs, values[i]); out[i] = dot (rhs, values[i]);
return out; return out;
@ -208,22 +151,25 @@ matrix<S,T>::operator* (const point<S,T> &rhs) const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
bool bool
matrix<S,T>::is_affine (void) const matrix<Rows,Cols,T>::is_affine (void) const
{ {
for (size_t i = 0; i < S - 1; ++i) if (Rows != Cols)
if (!exactly_zero (values[S-1][i]))
return false; return false;
return exactly_equal (values[S-1][S-1], T{1}); for (size_t i = 0; i < Rows - 1; ++i)
if (!exactly_zero (values[Rows-1][i]))
return false;
return exactly_equal (values[Rows-1][Rows-1], T{1});
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::ortho (T left, T right, matrix<Rows,Cols,T>::ortho (T left, T right,
T bottom, T top, T bottom, T top,
T near, T far) T near, T far)
{ {
@ -247,9 +193,9 @@ matrix<S,T>::ortho (T left, T right,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::ortho2D (T left, T right, matrix<Rows, Cols,T>::ortho2D (T left , T right,
T bottom, T top) T bottom, T top)
{ {
return ortho (left, right, bottom, top, -1, 1); return ortho (left, right, bottom, top, -1, 1);
@ -257,9 +203,9 @@ matrix<S,T>::ortho2D (T left, T right,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::perspective (T fov, T aspect, range<T> Z) matrix<Rows,Cols,T>::perspective (T fov, T aspect, range<T> Z)
{ {
CHECK_GE (Z.lo, 0); CHECK_GE (Z.lo, 0);
CHECK_GE (Z.hi, 0); CHECK_GE (Z.hi, 0);
@ -288,9 +234,9 @@ matrix<S,T>::perspective (T fov, T aspect, range<T> Z)
// Implemented for right handed world coordinates. // Implemented for right handed world coordinates.
// //
// Assumes 'up' is normalised. // Assumes 'up' is normalised.
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::look_at (const util::point<3,T> eye, matrix<Rows,Cols,T>::look_at (const util::point<3,T> eye,
const util::point<3,T> centre, const util::point<3,T> centre,
const util::vector<3,T> up) const util::vector<3,T> up)
{ {
@ -312,18 +258,18 @@ matrix<S,T>::look_at (const util::point<3,T> eye,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::translation (util::vector<2,T> v) matrix<Rows,Cols,T>::translation (util::vector<2,T> v)
{ {
return translation ({v.x, v.y, 0}); return translation ({v.x, v.y, 0});
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::translation (util::vector<3,T> v) matrix<Rows,Cols,T>::translation (util::vector<3,T> v)
{ {
return { { return { {
{ 1.f, 0.f, 0.f, v.x }, { 1.f, 0.f, 0.f, v.x },
@ -335,17 +281,17 @@ matrix<S,T>::translation (util::vector<3,T> v)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::scale (T mag) matrix<Rows,Cols,T>::scale (T mag)
{ {
return scale (vector<3,T> (mag)); return scale (vector<3,T> (mag));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::scale (util::vector<3,T> v) matrix<Rows,Cols,T>::scale (util::vector<3,T> v)
{ {
return { { return { {
{ v.x, 0.f, 0.f, 0.f }, { v.x, 0.f, 0.f, 0.f },
@ -357,9 +303,9 @@ matrix<S,T>::scale (util::vector<3,T> v)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix4<T> util::matrix4<T>
matrix<S,T>::rotation (T angle, util::vector<3,T> about) matrix<Rows,Cols,T>::rotation (T angle, util::vector<3,T> about)
{ {
CHECK (is_normalised (about)); CHECK (is_normalised (about));
@ -394,25 +340,26 @@ matrix<S,T>::rotation (T angle, util::vector<3,T> about)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template struct util::matrix<2,float>; template struct util::matrix<2,2,float>;
template struct util::matrix<2,double>; template struct util::matrix<2,2,double>;
template struct util::matrix<3,float>; template struct util::matrix<3,3,float>;
template struct util::matrix<3,double>; template struct util::matrix<3,3,double>;
template struct util::matrix<4,float>; template struct util::matrix<4,4,float>;
template struct util::matrix<4,double>; template struct util::matrix<4,4,double>;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Uses the algorithm from: // Uses the algorithm from:
// "Extracting Euler Angles from a Rotation Matrix" by // "Extracting Euler Angles from a Rotation Matrix" by
// Mike Day, Insomniac Games. // Mike Day, Insomniac Games.
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
util::vector<3,T> util::vector<3,T>
util::to_euler (const matrix<S,T> &m) util::to_euler (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 3 || S == 4, "only defined for 3d affine transforms"); static_assert (Rows == Cols && (Rows == 3 || Rows == 4),
"only defined for 3d affine transforms");
const auto theta0 = std::atan2 (m[2][1], m[2][2]); const auto theta0 = std::atan2 (m[2][1], m[2][2]);
@ -431,21 +378,21 @@ util::to_euler (const matrix<S,T> &m)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template util::vector<3,float> util::to_euler (const matrix<3,float>&); template util::vector<3,float> util::to_euler (const matrix<3,3,float>&);
template util::vector<3,float> util::to_euler (const matrix<4,float>&); template util::vector<3,float> util::to_euler (const matrix<4,4,float>&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
std::ostream& std::ostream&
util::operator<< (std::ostream &os, const matrix<S,T> &m) util::operator<< (std::ostream &os, const matrix<Rows,Cols,T> &m)
{ {
os << "{ "; os << "{ ";
for (size_t i = 0; i < S; ++i) { for (size_t i = 0; i < Rows; ++i) {
os << "{ "; os << "{ ";
std::copy (m[i], m[i]+S, util::infix_iterator<float> (os, ", ")); std::copy_n (m[i], Cols, util::infix_iterator<float> (os, ", "));
os << ((i == S - 1) ? " }" : " }, "); os << ((i == Rows - 1) ? " }" : " }, ");
} }
return os << " }"; return os << " }";
@ -453,5 +400,5 @@ util::operator<< (std::ostream &os, const matrix<S,T> &m)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template std::ostream& util::operator<< (std::ostream&, const matrix<4,float>&); template std::ostream& util::operator<< (std::ostream&, const matrix<4,4,float>&);
template std::ostream& util::operator<< (std::ostream&, const matrix<4,double>&); template std::ostream& util::operator<< (std::ostream&, const matrix<4,4,double>&);

View File

@ -21,14 +21,15 @@
#include "range.hpp" #include "range.hpp"
#include <ostream> #include <ostream>
#include <cstdlib>
namespace util { namespace util {
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
struct matrix { struct matrix {
T values[S][S]; static constexpr auto rows = Rows;
static constexpr auto cols = Cols;
static constexpr size_t rows = S; T values[Rows][Cols];
static constexpr size_t cols = S;
// index operators return a pointer into the data array so that // index operators return a pointer into the data array so that
// multidimensional array syntax can be used transparently on this // multidimensional array syntax can be used transparently on this
@ -46,9 +47,6 @@ namespace util {
const T* cbegin (void) const; const T* cbegin (void) const;
const T* cend (void) const; const T* cend (void) const;
matrix& transpose (void);
matrix transposed (void) const;
T determinant (void) const; T determinant (void) const;
matrix inverse (void) const; matrix inverse (void) const;
@ -56,29 +54,27 @@ namespace util {
matrix inverse_affine (void) const; matrix inverse_affine (void) const;
matrix& invert_affine (void); matrix& invert_affine (void);
matrix operator* (const matrix&) const; vector<Rows,T> operator* (const vector<Rows,T>&) const;
matrix& operator*=(const matrix&); point<Rows,T> operator* (const point<Rows,T> &) const;
vector<S,T> operator* (const vector<S,T>&) const;
point<S,T> operator* (const point<S,T> &) const;
bool is_affine (void) const; bool is_affine (void) const;
template <typename U> template <typename U>
matrix<S,U> cast (void) const; matrix<Rows,Cols,U>
cast (void) const;
// Perspective matrices // Perspective matrices
static matrix<4,T> ortho (T left, T right, T bottom, T top, T near, T far); static matrix<4,4,T> ortho (T left, T right, T bottom, T top, T near, T far);
static matrix<4,T> ortho2D (T left, T right, T bottom, T top); static matrix<4,4,T> ortho2D (T left, T right, T bottom, T top);
static matrix<4,T> perspective (T fov, T aspect, range<T> Z); static matrix<4,4,T> perspective (T fov, T aspect, range<T> Z);
static matrix<4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up); static matrix<4,4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up);
// Affine matrices // Affine matrices
static matrix<4,T> translation (util::vector<2,T>); static matrix<4,4,T> translation (util::vector<2,T>);
static matrix<4,T> translation (util::vector<3,T>); static matrix<4,4,T> translation (util::vector<3,T>);
static matrix<4,T> scale (util::vector<3,T>); static matrix<4,4,T> scale (util::vector<3,T>);
static matrix<4,T> scale (T); static matrix<4,4,T> scale (T);
static matrix<4,T> rotation (T angle, util::vector<3,T> about); static matrix<4,4,T> rotation (T angle, util::vector<3,T> about);
// Constant matrices // Constant matrices
static constexpr matrix identity (); static constexpr matrix identity ();
@ -91,101 +87,110 @@ namespace util {
// //
// Results are undefined if the matrix is not purely a rotation matrix, // Results are undefined if the matrix is not purely a rotation matrix,
// or if the dimension is not 3x3 or 4x4. // or if the dimension is not 3x3 or 4x4.
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
vector<3,T> vector<3,T>
to_euler (const matrix<S,T>&); to_euler (const matrix<Rows, Cols, T>&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// logical operations // logical operations
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
bool bool
operator== (const matrix<S,T>&, const matrix<S,T>&); operator== (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
bool bool
operator!= (const matrix<S,T>&, const matrix<S,T>&); operator!= (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// element operations // element operations
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
matrix<S,T> matrix<Rows,Cols,T>
operator+ (const matrix<S,T>&, const matrix<S,T>&); operator+ (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
matrix<S,T> matrix<Rows,Cols,T>
operator- (const matrix<S,T>&, const matrix<S,T>&); operator- (const matrix<Rows,Cols,T>&, const matrix<Rows,Cols,T>&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// scalar operations // scalar operations
template <size_t S, typename T> constexpr matrix<S,T> operator* (const matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator* (const matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T> operator/ (const matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator/ (const matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T> operator+ (const matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator+ (const matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T> operator- (const matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator- (const matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T> operator* (T, const matrix<S,T>&); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator* (T, const matrix<R,C,T>&);
template <size_t S, typename T> constexpr matrix<S,T> operator/ (T, const matrix<S,T>&); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator/ (T, const matrix<R,C,T>&);
template <size_t S, typename T> constexpr matrix<S,T> operator+ (T, const matrix<S,T>&); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator+ (T, const matrix<R,C,T>&);
template <size_t S, typename T> constexpr matrix<S,T> operator- (T, const matrix<S,T>&); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T> operator- (T, const matrix<R,C,T>&);
template <size_t S, typename T> constexpr matrix<S,T>& operator*= (matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator*= (matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T>& operator/= (matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator/= (matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T>& operator+= (matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator+= (matrix<R,C,T>&, T);
template <size_t S, typename T> constexpr matrix<S,T>& operator-= (matrix<S,T>&, T); template <size_t R, size_t C, typename T> constexpr matrix<R,C,T>& operator-= (matrix<R,C,T>&, T);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> // matrix operations
template <
size_t R1, size_t C1,
size_t R2, size_t C2,
typename T
> constexpr matrix<R1,C2,T> operator* (const matrix<R1,C1,T>&, const matrix<R2,C2,T>&);
///////////////////////////////////////////////////////////////////////////
template <size_t Rows, size_t Cols, typename T>
T T
determinant (const matrix<S,T>&); determinant (const matrix<Rows,Cols,T>&);
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>
inverse (const matrix<S,T>&); inverse (const matrix<Rows,Cols,T>&);
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Cols,Rows,T>
transposed (const matrix<S,T>&); transposed (const matrix<Rows,Cols,T>&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>
abs (const matrix<S,T>&); abs (const matrix<Rows,Cols,T>&);
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
T T
sum (const matrix<S,T>&); sum (const matrix<Rows,Cols,T>&);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template <typename T> using matrix3 = matrix<3,T>; template <typename T> using matrix3 = matrix<3,3,T>;
template <typename T> using matrix4 = matrix<4,T>; template <typename T> using matrix4 = matrix<4,4,T>;
template <size_t S> using matrixf = matrix<S,float>; template <size_t Rows, size_t Cols> using matrixf = matrix<Rows,Cols,float>;
template <size_t S> using matrixd = matrix<S,double>; template <size_t Rows, size_t Cols> using matrixd = matrix<Rows,Cols,double>;
typedef matrix<2,float> matrix2f; typedef matrix<2,2,float> matrix2f;
typedef matrix<2,double> matrix2d; typedef matrix<2,2,double> matrix2d;
typedef matrix<3,float> matrix3f; typedef matrix<3,3,float> matrix3f;
typedef matrix<3,double> matrix3d; typedef matrix<3,3,double> matrix3d;
typedef matrix<4,float> matrix4f; typedef matrix<4,4,float> matrix4f;
typedef matrix<4,double> matrix4d; typedef matrix<4,4,double> matrix4d;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
std::ostream& operator<< (std::ostream&, const matrix<S,T>&); std::ostream& operator<< (std::ostream&, const matrix<Rows,Cols,T>&);
} }
#include "matrix.ipp" #include "matrix.ipp"

View File

@ -23,102 +23,102 @@
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T* T*
util::matrix<S,T>::operator[] (size_t idx) util::matrix<Rows,Cols,T>::operator[] (size_t idx)
{ {
return this->values[idx]; return this->values[idx];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::operator[] (size_t idx) const util::matrix<Rows,Cols,T>::operator[] (size_t idx) const
{ {
return this->values[idx]; return this->values[idx];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T* T*
util::matrix<S,T>::data (void) util::matrix<Rows,Cols,T>::data (void)
{ {
return begin (); return begin ();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::data (void) const util::matrix<Rows,Cols,T>::data (void) const
{ {
return begin (); return begin ();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::begin (void) const util::matrix<Rows,Cols,T>::begin (void) const
{ {
return &(*this)[0][0]; return &(*this)[0][0];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::end (void) const util::matrix<Rows,Cols,T>::end (void) const
{ {
return &(*this)[S][0]; return &(*this)[Rows][0];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::cbegin (void) const util::matrix<Rows,Cols,T>::cbegin (void) const
{ {
return begin (); return begin ();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
const T* const T*
util::matrix<S,T>::cend (void) const util::matrix<Rows,Cols,T>::cend (void) const
{ {
return end (); return end ();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T* T*
util::matrix<S,T>::begin (void) util::matrix<Rows,Cols,T>::begin (void)
{ {
return &(*this)[0][0]; return &(*this)[0][0];
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T* T*
util::matrix<S,T>::end (void) util::matrix<Rows,Cols,T>::end (void)
{ {
return &(*this)[S][0]; return &(*this)[Rows][0];
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
template <typename U> template <typename U>
util::matrix<S,U> util::matrix<Rows,Cols,U>
util::matrix<S,T>::cast (void) const util::matrix<Rows,Cols,T>::cast (void) const
{ {
util::matrix<S,U> out; util::matrix<Rows,Cols,T> out;
std::copy (cbegin (), cend (), std::begin (out)); std::copy (cbegin (), cend (), std::begin (out));
return out; return out;
} }
@ -126,14 +126,14 @@ util::matrix<S,T>::cast (void) const
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define MATRIX_ELEMENT_OP(OP) \ #define MATRIX_ELEMENT_OP(OP) \
template <size_t S, typename T> \ template <size_t Rows, size_t Cols, typename T> \
constexpr \ constexpr \
util::matrix<S,T> \ util::matrix<Rows,Cols,T> \
util::operator OP ( \ util::operator OP ( \
const util::matrix<S,T> &a, \ const util::matrix<Rows,Cols,T> &a, \
const util::matrix<S,T> &b) \ const util::matrix<Rows,Cols,T> &b) \
{ \ { \
util::matrix<S,T> res {}; \ util::matrix<Rows,Cols,T> res {}; \
\ \
for (size_t i = 0; i < a.rows; ++i) \ for (size_t i = 0; i < a.rows; ++i) \
for (size_t j = 0; j < a.cols; ++j) \ for (size_t j = 0; j < a.cols; ++j) \
@ -150,12 +150,12 @@ MATRIX_ELEMENT_OP(+)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define MATRIX_SCALAR_OP(OP) \ #define MATRIX_SCALAR_OP(OP) \
template <size_t S, typename T> \ template <size_t Rows, size_t Cols, typename T> \
constexpr \ constexpr \
util::matrix<S,T> \ util::matrix<Rows,Cols,T> \
util::operator OP (const util::matrix<S,T> &m, const T t) \ util::operator OP (const util::matrix<Rows,Cols,T> &m, const T t) \
{ \ { \
util::matrix<S,T> res {}; \ util::matrix<Rows,Cols,T> res {}; \
\ \
std::transform ( \ std::transform ( \
std::cbegin (m), \ std::cbegin (m), \
@ -168,19 +168,19 @@ util::operator OP (const util::matrix<S,T> &m, const T t) \
} \ } \
\ \
\ \
template <size_t S, typename T> \ template <size_t Rows, size_t Cols, typename T> \
constexpr \ constexpr \
util::matrix<S,T> \ util::matrix<Rows,Cols,T> \
util::operator OP (const T t, const util::matrix<S,T> &m) \ util::operator OP (const T t, const util::matrix<Rows,Cols,T> &m) \
{ \ { \
return m OP t; \ return m OP t; \
} \ } \
\ \
\ \
template <size_t S, typename T> \ template <size_t Rows, size_t Cols, typename T> \
constexpr \ constexpr \
util::matrix<S,T>& \ util::matrix<Rows,Cols,T>& \
util::operator OP##= (util::matrix<S,T> &m, T t) \ util::operator OP##= (util::matrix<Rows,Cols,T> &m, T t) \
{ \ { \
std::transform ( \ std::transform ( \
std::cbegin (m), \ std::cbegin (m), \
@ -202,64 +202,89 @@ MATRIX_SCALAR_OP(-)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <
std::size_t R1, std::size_t C1,
std::size_t R2, std::size_t C2,
typename T
>
constexpr constexpr
util::matrix<S,T> util::matrix<R1,C2,T>
util::matrix<S,T>::zeroes (void) util::operator* (const matrix<R1,C1,T> &a, const matrix<R2,C2,T> &b)
{
static_assert (R2 == C1);
matrix<R1,C2,T> res {0};
for (size_t r = 0; r < R1; ++r)
for (size_t c = 0; c < C2; ++c)
for (size_t i = 0; i < R2; ++i)
res[r][c] += a[r][i] * b[i][c];
return res;
}
///////////////////////////////////////////////////////////////////////////////
template <size_t Rows, size_t Cols, typename T>
constexpr
util::matrix<Rows,Cols,T>
util::matrix<Rows,Cols,T>::zeroes (void)
{ {
return {0}; return {0};
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
util::matrix<S,T> util::matrix<Rows,Cols,T>
util::matrix<S,T>::identity (void) util::matrix<Rows,Cols,T>::identity (void)
{ {
static_assert (Rows == Cols);
auto m = zeroes (); auto m = zeroes ();
for (size_t i = 0; i < S; ++i) for (size_t i = 0; i < Rows; ++i)
m[i][i] = 1; m[i][i] = 1;
return m; return m;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
bool bool
util::operator== (const matrix<S,T> &a, const matrix<S,T> &b) util::operator== (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
{ {
return std::equal (std::cbegin (a), std::cend (a), std::cbegin (b)); return std::equal (std::cbegin (a), std::cend (a), std::cbegin (b));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
bool bool
util::operator!= (const matrix<S,T> &a, const matrix<S,T> &b) util::operator!= (const matrix<Rows,Cols,T> &a, const matrix<Rows,Cols,T> &b)
{ {
return !(a == b); return !(a == b);
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
util::matrix<S,T> util::matrix<Rows,Cols,T>
util::abs (const util::matrix<S,T> &src) util::abs (const util::matrix<Rows,Cols,T> &src)
{ {
util::matrix<S,T> dst; util::matrix<Rows,Cols,T> dst;
std::transform (std::cbegin (src), std::cend (src), std::begin (dst), util::abs<T>); std::transform (std::cbegin (src), std::cend (src), std::begin (dst), util::abs<T>);
return dst; return dst;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
constexpr constexpr
T T
util::sum (const util::matrix<S,T> &src) util::sum (const util::matrix<Rows, Cols,T> &src)
{ {
return sum (std::cbegin (src), std::cend (src)); return sum (std::cbegin (src), std::cend (src));
} }

View File

@ -20,27 +20,27 @@ using util::matrix;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T T
util::determinant (const matrix<S,T> &m) util::determinant (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 2, "partial specialization for 2 dimensions"); static_assert (Rows == 2 && Cols == 2);
return m[0][0] * m[1][1] - m[0][1] * m[1][0]; return m[0][0] * m[1][1] - m[0][1] * m[1][0];
} }
template float util::determinant (const matrix<2,float>&); template float util::determinant (const matrix<2,2,float>&);
template double util::determinant (const matrix<2,double>&); template double util::determinant (const matrix<2,2,double>&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>
util::inverse (const matrix<S,T> &m) util::inverse (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 2, "partial specialization for 2 dimensions"); static_assert (Rows == 2 && Cols == 2);
return matrix<S,T> { return matrix<2,2,T> {
m[1][1], -m[0][1], m[1][1], -m[0][1],
-m[1][0], m[0][0] -m[1][0], m[0][0]
} / determinant (m); } / determinant (m);
@ -48,10 +48,10 @@ util::inverse (const matrix<S,T> &m)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template util::matrix<2,float> util::inverse (const matrix<2,float>&); template util::matrix<2,2,float> util::inverse (const matrix<2,2,float>&);
template util::matrix<2,double> util::inverse (const matrix<2,double>&); template util::matrix<2,2,double> util::inverse (const matrix<2,2,double>&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template struct util::matrix<2,float>; template struct util::matrix<2,2,float>;
template struct util::matrix<2,double>; template struct util::matrix<2,2,double>;

View File

@ -20,29 +20,29 @@ using util::matrix;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T T
util::determinant (const matrix<S,T>& m) util::determinant (const matrix<Rows,Cols,T>& m)
{ {
static_assert (S == 3, "hard coded 3x3 specialisation"); static_assert (Rows == 3 && Cols == 3);
return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - return m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) -
m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +
m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
} }
template float util::determinant (const matrix<3,float>&); template float util::determinant (const matrix<3,3,float>&);
template double util::determinant (const matrix<3,double>&); template double util::determinant (const matrix<3,3,double>&);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>
util::inverse (const matrix<S,T> &m) util::inverse (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 3, "hard coded 3x3 specialisation"); static_assert (Rows == 3 && Cols == 3);
return matrix<S,T> { return matrix<3,3,T> {
m[1][1] * m[2][2] - m[2][1] * m[1][2], m[1][1] * m[2][2] - m[2][1] * m[1][2],
m[0][2] * m[2][1] - m[0][1] * m[2][2], m[0][2] * m[2][1] - m[0][1] * m[2][2],
m[0][1] * m[1][2] - m[0][2] * m[1][1], m[0][1] * m[1][2] - m[0][2] * m[1][1],
@ -57,10 +57,10 @@ util::inverse (const matrix<S,T> &m)
} / determinant (m); } / determinant (m);
} }
template util::matrix<3,float> util::inverse (const matrix<3,float>&); template util::matrix<3,3,float> util::inverse (const matrix<3,3,float>&);
template util::matrix<3,double> util::inverse (const matrix<3,double>&); template util::matrix<3,3,double> util::inverse (const matrix<3,3,double>&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template struct util::matrix<3,float>; template struct util::matrix<3,3,float>;
template struct util::matrix<3,double>; template struct util::matrix<3,3,double>;

View File

@ -20,11 +20,11 @@ using util::matrix;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
T T
util::determinant (const matrix<S,T> &m) util::determinant (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 4, "hard coded 4x4 specialisation"); static_assert (Rows == 4 && Cols == 4);
return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] - return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] -
m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] + m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] +
@ -40,18 +40,18 @@ util::determinant (const matrix<S,T> &m)
m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3];
} }
template float util::determinant (const matrix<4,float>&); template float util::determinant (const matrix<4,4,float>&);
template double util::determinant (const matrix<4,double>&); template double util::determinant (const matrix<4,4,double>&);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
template <size_t S, typename T> template <size_t Rows, size_t Cols, typename T>
matrix<S,T> matrix<Rows,Cols,T>
util::inverse (const matrix<S,T> &m) util::inverse (const matrix<Rows,Cols,T> &m)
{ {
static_assert (S == 4, "hard coded 4x4 specialisation"); static_assert (Rows == 4 && Cols == 4);
return matrix<S,T> { return matrix<4,4,T> {
m[1][2]*m[2][3]*m[3][1] - m[1][3]*m[2][2]*m[3][1] + m[1][3]*m[2][1]*m[3][2] - m[1][1]*m[2][3]*m[3][2] - m[1][2]*m[2][1]*m[3][3] + m[1][1]*m[2][2]*m[3][3], m[1][2]*m[2][3]*m[3][1] - m[1][3]*m[2][2]*m[3][1] + m[1][3]*m[2][1]*m[3][2] - m[1][1]*m[2][3]*m[3][2] - m[1][2]*m[2][1]*m[3][3] + m[1][1]*m[2][2]*m[3][3],
m[0][3]*m[2][2]*m[3][1] - m[0][2]*m[2][3]*m[3][1] - m[0][3]*m[2][1]*m[3][2] + m[0][1]*m[2][3]*m[3][2] + m[0][2]*m[2][1]*m[3][3] - m[0][1]*m[2][2]*m[3][3], m[0][3]*m[2][2]*m[3][1] - m[0][2]*m[2][3]*m[3][1] - m[0][3]*m[2][1]*m[3][2] + m[0][1]*m[2][3]*m[3][2] + m[0][2]*m[2][1]*m[3][3] - m[0][1]*m[2][2]*m[3][3],
m[0][2]*m[1][3]*m[3][1] - m[0][3]*m[1][2]*m[3][1] + m[0][3]*m[1][1]*m[3][2] - m[0][1]*m[1][3]*m[3][2] - m[0][2]*m[1][1]*m[3][3] + m[0][1]*m[1][2]*m[3][3], m[0][2]*m[1][3]*m[3][1] - m[0][3]*m[1][2]*m[3][1] + m[0][3]*m[1][1]*m[3][2] - m[0][1]*m[1][3]*m[3][2] - m[0][2]*m[1][1]*m[3][3] + m[0][1]*m[1][2]*m[3][3],
@ -71,10 +71,10 @@ util::inverse (const matrix<S,T> &m)
} / determinant (m); } / determinant (m);
} }
template util::matrix<4,float> util::inverse (const matrix<4,float>&); template util::matrix<4,4,float> util::inverse (const matrix<4,4,float>&);
template util::matrix<4,double> util::inverse (const matrix<4,double>&); template util::matrix<4,4,double> util::inverse (const matrix<4,4,double>&);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
template struct util::matrix<4,float>; template struct util::matrix<4,4,float>;
template struct util::matrix<4,double>; template struct util::matrix<4,4,double>;