matrix operations

# QVM: Quaternions, Vectors, Matrices

### Matrix Operations

#include <boost/qvm/mat_operations.hpp>

    namespace boost
    {
        namespace qvm
        {
            //*** Matrix operations ***

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            A & assign( A & a, B const & b );

            //Only enabled if:
            //  is_mat<R>::value && is_mat<A>::value &&
            //  mat_traits<R>::rows==mat_traits<A>::rows &&
            //  mat_traits<R>::cols==mat_traits<A>::cols
            template <class R,class A>
            R convert_to( A const & a );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            A & operator-=( A & a, B const & b );

            //Only enabled if: is_mat<A>::value
            template <class A>
            typename deduce_mat<A>::type
            operator-( A const & a );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type
            operator-( A const & a, B const & b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            A & operator+=( A & a, B const & b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type
            operator+( A const & a, B const & b );

            //Only enabled if: is_mat<A>::value && is_scalar<B>::value
            template <class A,class B>
            A & operator/=( A & a, B b );

            //Only enabled if: is_mat<A>::value && is_scalar<B>::value
            template <class A,class B>
            typename deduce_mat<A>::type
            operator/( A const & a, B b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<A>::cols &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            A & operator*=( A & a, B const & b );

            //Only enabled if: is_mat<A>::value && is_scalar<B>::value
            template <class A,class B>
            A & operator*=( A & a, B b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::cols==mat_traits<B>::rows
            template <class A,class B>
            typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols>::type
            operator*( A const & a, B const & b );

            //Only enabled if: is_mat<A>::value && is_scalar<B>::value
            template <class A,class B>
            typename deduce_mat<A>::type
            operator*( A const & a, B b );

            //Only enabled if: is_scalar<A>::value && is_mat<B>::value
            template <class A,class B>
            typename deduce_mat<B>::type
            operator*( A a, B const & b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            bool operator==( A const & a, B const & b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B>
            bool operator!=( A const & a, B const & b );

            //Only enabled if:
            //  is_mat<A>::value && is_mat<B>::value &&
            //  mat_traits<A>::rows==mat_traits<B>::rows &&
            //  mat_traits<A>::cols==mat_traits<B>::cols
            template <class A,class B,class Cmp>
            bool cmp( A const & a, B const & b, Cmp pred );

            //Only enabled if:
            //  is_mat<A>::value && is_scalar<B>::value
            //  mat_traits<A>::rows==mat_traits<A>::cols

            template <class A,class B>
            typename deduce_mat<A>::type
            inverse( A const & a, B det );

            template <class A>
            typename deduce_mat<A>::type
            inverse( A const & a );

            template <class T,int D>
            -unspecified-return-type- zero_mat();

            template <class T,int R,int C>
            -unspecified-return-type- zero_mat();

            //Only enabled if:
            //  is_mat<A>::value
            template <class A>
            void set_zero( A & a );

            template <class S,int D>
            -unspecified-return-type- identity_mat();

            //Only enabled if:
            //  is_mat<A>::value &&
            //  mat_traits<A>::cols==mat_traits<A>::rows
            template <class A>
            void set_identity( A & a );

            //Only enabled if:
            //  is_vec<A>::value && vec_traits<A>::dim==3
            template <int Dim,class A,class Angle>
            -unspecified-return-type-
            rot_mat( A const & axis, Angle angle );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_xzy( Angle x1, Angle z2, Angle y3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_xyz( Angle x1, Angle y2, Angle z3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_yxz( Angle y1, Angle x2, Angle z3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_yzx( Angle y1, Angle z2, Angle x3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_zyx( Angle z1, Angle y2, Angle x3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_zxy( Angle z1, Angle x2, Angle y3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_xzx( Angle x1, Angle z2, Angle x3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_xyx( Angle x1, Angle y2, Angle x3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_yxy( Angle y1, Angle x2, Angle y3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_yzy( Angle y1, Angle z2, Angle y3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_zyz( Angle z1, Angle y2, Angle z3 );

            template <int Dim,class Angle>
            -unspecified-return-type-
            rot_mat_zxz( Angle z1, Angle y2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols &&
            //  is_vec<B>::value && vec_traits<B>::dim==3
            template <class A>
            void set_rot( A & a, B const & axis, typename vec_traits<B>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_xzy( A & a, Angle x1, Angle z2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_xyz( A & a, Angle x1, Angle y2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_yxz( A & a, Angle y1, Angle x2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_yzx( A & a, Angle y1, Angle z2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_zyx( A & a, Angle z1, Angle y2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_zxy( A & a, Angle z1, Angle x2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_xzx( A & a, Angle x1, Angle z2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_xyx( A & a, Angle x1, Angle y2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_yxy( A & a, Angle y1, Angle x2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_yzy( A & a, Angle y1, Angle z2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_zyz( A & a, Angle z1, Angle y2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_zxz( A & a, Angle z1, Angle x2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void set_rot_xzy( A & a, Angle x1, Angle z2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols &&
            //  is_vec<B>::value && vec_traits<B>::dim==3
            template <class A,class B>
            void rotate( A & a, B const & axis, typename mat_traits<A>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_xzy( A & a, Angle x1, Angle z2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_xyz( A & a, Angle x1, Angle y2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_yxz( A & a, Angle y1, Angle x2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_yzx( A & a, Angle y1, Angle z2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_zyx( A & a, Angle z1, Angle y2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_zxy( A & a, Angle z1, Angle x2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_xzx( A & a, Angle x1, Angle z2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_xyx( A & a, Angle x1, Angle y2, Angle x3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_yxy( A & a, Angle y1, Angle x2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_yzy( A & a, Angle y1, Angle z2, Angle y3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_zyz( A & a, Angle z1, Angle y2, Angle z3 );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A,class Angle>
            void rotate_zxz( A & a, Angle z1, Angle x2, Angle z3 );

            template <int Dim,class Angle>
            -unspecified-return-type- rotx_mat( Angle const & angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void set_rotx( A & a, typename mat_traits<A>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void rotate_x( A & a, typename mat_traits<A>::scalar_type angle );

            template <int Dim,class Angle>
            -unspecified-return-type- roty_mat( Angle const & angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void set_roty( A & a, typename mat_traits<A>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void rotate_y( A & a, typename mat_traits<A>::scalar_type angle );

            template <int Dim,class Angle>
            -unspecified-return-type- rotz_mat( Angle const & angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void set_rotz( A & a, typename mat_traits<A>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows>=3 &&
            //  mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            void rotate_z( A & a, typename mat_traits<A>::scalar_type angle );

            //Only enabled if:
            //  is_mat<A>::value && mat_traits<A>::rows==mat_traits<A>::cols
            template <class A>
            mat_traits<A>::scalar_type
            determinant( A const & a );

            template <class T>
            -unspecified-return-type
            perspective_lh( T fov_y, T aspect, T zn, T zf );

            template <class T>
            -unspecified-return-type
            perspective_rh( T fov_y, T aspect, T zn, T zf );

            //Only enabled if: is_mat<A>::value
            template <class A>
            -unspecified-return-type- mref( A & a );

            //Only enabled if: is_mat<A>::value
            template <class Scalar,class A>
            -unspecified-return_type- scalar_cast( A const & a );
        }
    }

This is a list of all matrix operations implemented by Boost QVM -- click on functions for individual documentation. General notes:

- All functions use SFINAE/enable_if. They are available for any C++ type but only if it has been registered through the mat_traits template.
- When objects are returned by value their type is deduced either by the deduce_mat template (for unary functions) or the deduce_mat2 template (for binary functions).
- The type of scalar arguments is deduced independently from the type of the matrix argument, so they are not required to match. Scalar arguments must convert implicitly to the matrix scalar type.

See also: Boost QVM | Synopsis