QVM: Quaternions, Vectors, Matrices

mat_traits

#include <boost/qvm/mat_traits.hpp>

namespace boost
{
    namespace qvm
    {
        template <class M>
        struct mat_traits
        {
            /*main template members unspecified*/
        };
        
        /*
        User-defined (possibly partial) specializations:
        
        template <>
        struct mat_traits<M>
        {
            static int const rows = /*user-defined*/;        
            static int const cols = /*user-defined*/;        
            typedef /*user-defined*/ scalar_type;        
        
            template <int R,int C> static inline scalar_type read_element( Matrix const & m );        
            template <int R,int C> static inline scalar_type & write_element( Matrix & m );        
        
            static inline scalar_type read_element_idx( int r, int c, Matrix const & m );        
            static inline scalar_type & write_element_idx( int r, int c, Matrix & m );        
        };
        */
    }
}

The mat_traits template must be specialized for (user-defined) matrix types in order to enable vector and matrix operations defined in Boost QVM headers for objects of those types.

Note: matrix types are not required to be copyable.

The main mat_traits template members are not specified. Valid specializations are required to define the following members:

  • rows: the expression mat_traits<Matrix>::rows must evaluate to a compile-time integer constant greater than 0 that specifies the number of rows in a matrix.
  • cols must evaluate to a compile-time integer constant greater than 0 that specifies the number of columns in a matrix.
  • scalar_type: the expression mat_traits<Matrix>::scalar_type must be a value type which satisfies the scalar requirements.

In addition, valid specializations of the mat_traits template may define the following access functions as static members, where m is an object of type Matrix, R and C are compile-time integer constants, and r and c are variables of type int:

  • read_element: the expression mat_traits<Matrix>::read_element<R,C>(m) returns either a copy of or a const reference to the element at row R and column C of m.
  • write_element: the expression mat_traits<Matrix>::write_element<R,C>(m) returns mutable reference to the element at row R and column C of m.
  • read_element_idx: the expression mat_traits<Matrix>::read_element_idx(r,c,m) returns either a copy of or a const reference to the element at row r and column c of m.
  • write_element_idx: the expression mat_traits<Matrix>::write_element_idx(r,c,m) returns mutable reference to the element at row r and column c of m.

It is illegal to call any of the above functions unless is_mat<Matrix>::value is true. Even then, matrix types are allowed to define only a subset of the access functions. The general requirements are:

Below is an example of a user-defined 3x3 matrix type, and its corresponding specialization of the mat_traits template:

#include <boost/qvm/mat_traits.hpp>

struct float33 { float a[3][3]; };

namespace boost
{
    namespace qvm
    {
        template <>
        struct mat_traits<float33>
        {
            static int const rows=3;
            static int const cols=3;
            typedef float scalar_type;

            template <int R,int C> static inline scalar_type & write_element( float33 & m ) { return m.a[R][C]; }
            template <int R,int C> static inline scalar_type read_element( float33 const & m ) { return m.a[R][C]; }

            static inline scalar_type & write_element_idx( int r, int c, float33 & m ) { return m.a[r][c]; }
            static inline scalar_type read_element_idx( int r, int c, float33 const & m ) { return m.a[r][c]; }
        };
    }
}

Equivalently, we could use the mat_traits_defaults template to shorten the above to:

namespace boost
{
    namespace qvm
    {
        template <>
        struct mat_traits<float33>: mat_traits_defaults<float33,float,3,3>
        {
            template <int R,int C> static inline scalar_type & write_element( float33 & m ) { return m.a[R][C]; }

            static inline scalar_type & write_element_idx( int r, int c, float33 & m ) { return m.a[r][c]; }
        };
    }
}