# 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:

- At least one of read_element or write_element must be defined;
- If read_element_idx is defined, read_element must also be defined;
- If write_element_idx is defined, write_element must also be defined.

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]; }
            };
        }
    }

See also: assign(mat,mat) | boost/qvm/mat_traits.hpp | boost/qvm/mat_traits_array.hpp | boost/qvm/mat_traits_defaults.hpp | cmp(mat,mat) | convert_to(mat) | convert_to(quat) | deduce_mat | deduce_mat2 | determinant | inverse(mat) | is_mat | mat | mat_traits<M>::read_element | mat_traits<M>::read_element_idx | mat_traits<M>::scalar_type | mat_traits<M>::write_element | mat_traits<M>::write_element_idx | mat_traits<Matrix>::cols | mat_traits<Matrix>::rows | mat_traits_defaults | operator!=(mat,mat) | operator*(mat,mat) | operator*(mat,vec) | operator*(vec,mat) | operator*=(mat,mat) | operator+(mat,mat) | operator+=(mat,mat) | operator-(mat,mat) | operator-=(mat,mat) | operator==(mat,mat) | rotate(mat,vec,scalar) | rotate_x(mat,scalar) | rotate_y(mat,scalar) | rotate_z(mat,scalar) | SFINAE/enable_if | scalar | set_identity(mat) | set_rot(mat,vec,scalar) | set_rotx(mat,scalar) | set_roty(mat,scalar) | set_rotz(mat,scalar) | set_zero(mat) | transform_point | transform_vector | translation | View Proxy