Source: https://www.boost.org/doc/libs/1_70_0/libs/qvm/doc/html/index.html
Timestamp: 2019-04-24 18:45:47+00:00

Document:
Emphasis on 2, 3 and 4-dimensional operations needed in graphics, video games and simulation applications.
Free function templates operate on any compatible user-defined quaternion, vector or matrix type.
Quaternion, vector and matrix types from different libraries or subsystems can be safely mixed in the same expression.
Type-safe mapping between compatible lvalue types with no temporary objects; e.g. transpose remaps the elements, rather than transforming the matrix.
The usual quaternion, vector and matrix operations work on these QVM types, however the operations are decoupled from any specific type: they work on any suitable type that has been registered by specializing the quat_traits, vec_traits and mat_traits templates.
User-defined quaternion types are similarly introduced to QVM by specializing the quat_traits template.
The expression col<1>(m) is an lvalue of an unspecified 3D vector type that refers to column 1 of m. Note however that this does not create any temporary objects; instead operator*= above works directly with a reference to m.
In general, the various view proxy functions return references of unspecified, non-copyable types that refer to the original object. They can be assigned from or converted to any compatible vector or matrix type.
QVM defines all permutations of X, Y, Z, W for 1D, 2D, 3D and 4D swizzling, plus each dimension defines variants with 0 or 1 used at any position (if 0 or 1 appear at the first position, the swizzling function name begins with underscore, e.g. _1XY).
SFINAE stands for Substitution Failure Is Not An Error. This refers to a situation in C++ where an invalid substitution of template parameters (including when those parameters are deduced implicitly as a result of an unqualified call) is not in itself an error.
In absence of concepts support, SFINAE can be used to disable function template overloads that would otherwise present a signature that is too generic. More formally, this is supported by the Boost enable_if library.
Even if the function definition might contain code that would compile only for Matrix and Vector types, because the function declaration itself is valid, it will participate in overload rezolutions when multiplying objects of any two types whatsoever. This typically renders overload resolutions ambiguous and the compiler (correctly) issues an error.
For brevity, function declarations throughout this documentation specify the condition which controls whether they are enabled or not without specifying exactly what enable_if construct is used to achieve this effect.
Whenever such overloads are compatible with a given expression, their signature is extremely generic, which means that any other (user-defined) compatible overload will be a better match in any overload resolution.
Bringing the entire boost::qvm namespace in scope may introduce ambiguities when accessing types (as opposed to functions) defined by 3rd-party libraries. In that case, you can safely bring namespace boost::qvm::sfinae in scope instead, which contains only function and operator overloads that use SFINAE/enable_if.
Bringing the boost::qvm namespace in scope lets you mix vector and matrix types that come from different APIs into a common, type-safe framework. In this case however, it should be considered what types should be returned by binary operations that return an object by value. For example, if you multiply a 3x3 matrix m1 of type user_matrix1 by a 3x3 matrix m2 of type user_matrix2, what type should that operation return?
Be mindful of potential ODR violation when using deduce_quat2, deduce_vec2 and deduce_mat2 in independent libraries. For example, this could happen if lib1 defines deduce_vec2<lib1::vec,lib2::vec>::type as lib1::vec and in the same program lib2 defines deduce_vec2<lib1::vec,lib2::vec>::type as lib2::vec.
It is best to keep such specializations out of lib1 and lib2. Of course, it is always safe for lib1 and lib2 to use convert_to to convert between the lib1::vec and lib2::vec types as needed.
Above, the object returned by inverse and captured by inv can not be of type float, because that type isn’t copyable. By default, QVM "just works", returning an object of suitable matrix type that is copyable. This deduction process can be controlled, by specializing the deduce_mat template.
QVM is split into multiple headers to allow different compilation units to #include only the components they need. Each function in this document specifies the exact header that must be #included in order to use it.
The tables below list commonly used components and the headers they’re found in. Header names containing a number define functions that only work with objects of that dimension; e.g. vec_operations2.hpp contains only functions for working with 2D vectors.
The header boost/qvm/all.hpp is provided for convenience. It includes all other QVM headers.
QVM is designed to work with user-defined quaternion, vector and matrix types, as well as user-defined scalar types. This section formally defines the way such types can be integrated.
In addition, the expression S(0) should construct a scalar of value zero, and S(1) should construct a scalar of value one, or else the scalar_traits template must be specialized appropriately.
This template defines a compile-time boolean constant value which can be used to determine whether a type T is a valid scalar type. It must be specialized together with the scalar_traits template in order to introduce a user-defined scalar type to QVM. Such types must satisfy the scalar requirements.
This template may be specialized for user-defined scalar types to define the appropriate conversion from int; this is primarily used whenever QVM needs to deduce a zero or one value.
A and B satisfy the scalar requirements.
else, if one of A or B is a signed integer and the other type is unsigned integer, the signed type is changed to unsigned, and then the lesser of the two integers is promoted to the other.
This template is used by generic binary operations that return a scalar, to deduce the return type based on the (possibly different) scalars of their arguments.
The expression quat_traits<T>::scalar_type evaluates to the scalar type of the quaternion type T (if is_quat<T>::value is true).
The expression vec_traits<T>::scalar_type evaluates to the scalar type of the vector type T (if is_vec<T>::value is true).
The expression mat_traits<T>::scalar_type evaluates to the scalar type of the matrix type T (if is_mat<T>::value is true).
The expression scalar<T>::type is similar, except that it automatically detects whether T is a vector or a matrix or a quaternion type.
This type template defines a compile-time boolean constant value which can be used to determine whether a type T is a quaternion type. For quaternion types, the quat_traits template can be used to access their elements generically, or to obtain their scalar type.
The quat_traits template must be specialized for (user-defined) quaternion types in order to enable quaternion operations defined in QVM headers for objects of those types.
QVM quaternion operations do not require that quaternion types are copyable.
scalar_type: the expression quat_traits<Quaternion>::scalar_type must be a value type which satisfies the scalar requirements.
read_element: the expression quat_traits<Quaternion>::read_element<I>(q) returns either a copy of or a const reference to the I-th element of q.
write_element: the expression quat_traits<Quaternion>::write_element<I>(q) returns mutable reference to the I-th element of q.
For the quaternion a + bi + cj + dk, the elements are assumed to be in the following order: a, b, c, d; that is, I=0/1/2/3 would access a/b/c/d.
It is illegal to call any of the above functions unless is_quat<Quaternion>::value is true. Even then, quaternion types are allowed to define only a subset of the access functions.
The quat_traits_defaults template is designed to be used as a public base for user-defined specializations of the quat_traits template, to easily define the required members. If it is used, the only member that must be defined by the user in a quat_traits specialization is write_element; the quat_traits_defaults base will define read_element, as well as scalar_type automatically.
This template is used by QVM whenever it needs to deduce a copyable quaternion type from a single user-supplied function parameter of quaternion type. Note that Q itself may be non-copyable.
The main template definition returns Q, which means that it is suitable only for copyable quaternion types. QVM also defines (partial) specializations for the non-copyable quaternion types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_quat template is for specifying the preferred quaternion type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
The main template definition returns an unspecified quaternion type with scalar_type obtained by deduce_scalar<A,B>::type, except if A and B are the same quaternion type Q, in which case Q is returned, which is only suitable for copyable types. QVM also defines (partial) specializations for the non-copyable quaternion types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_quat2 template is for specifying the preferred quaternion type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
This type template defines a compile-time boolean constant value which can be used to determine whether a type T is a vector type. For vector types, the vec_traits template can be used to access their elements generically, or to obtain their dimension and scalar type.
The vec_traits template must be specialized for (user-defined) vector types in order to enable vector and matrix operations defined in QVM headers for objects of those types.
QVM vector operations do not require that vector types are copyable.
dim: the expression vec_traits<Vector>::dim must evaluate to a compile-time integer constant greater than 0 that specifies the vector size.
scalar_type: the expression vec_traits<Vector>::scalar_type must be a value type which satisfies the scalar requirements.
read_element: the expression vec_traits<Vector>::read_element<I>(v) returns either a copy of or a const reference to the I-th element of v.
write_element: the expression vec_traits<Vector>::write_element<I>(v) returns mutable reference to the I-th element of v.
read_element_idx: the expression vec_traits<Vector>::read_element_idx(i,v) returns either a copy of or a const reference to the i-th element of v.
write_element_idx: the expression vec_traits<Vector>::write_element_idx(i,v) returns mutable reference to the i-th element of v.
If write_element_idx is defined, write_element must also be defined.
The vec_traits_defaults template is designed to be used as a public base for user-defined specializations of the vec_traits template, to easily define the required members. If it is used, the only member that must be defined by the user in a vec_traits specialization is write_element; the vec_traits_defaults base will define read_element, as well as scalar_type and dim automatically.
Optionally, the user may also define write_element_idx, in which case the vec_traits_defaults base will provide a suitable read_element_idx definition automatically. If not, vec_traits_defaults defines a protected implementation of write_element_idx which may be made publicly available by the deriving vec_traits specialization in case the vector type for which it is being specialized can not be indexed efficiently. This write_element_idx function is less efficient (using meta-programming), implemented in terms of the required user-defined write_element.
This template is used by QVM whenever it needs to deduce a copyable vector type of certain dimension from a single user-supplied function parameter of vector type. The returned type must have accessible copy constructor. Note that V may be non-copyable.
The main template definition returns an unspecified copyable vector type of size Dim, except if vec_traits<V>::dim==Dim, in which case it returns V, which is suitable only if V is a copyable type. QVM also defines (partial) specializations for the non-copyable vector types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_vec template is for specifying the preferred vector type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
The main template definition returns an unspecified vector type of the requested dimension with scalar_type obtained by deduce_scalar<A,B>::type, except if A and B are the same vector type V of dimension Dim, in which case V is returned, which is only suitable for copyable types. QVM also defines (partial) specializations for the non-copyable vector types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_vec2 template is for specifying the preferred vector type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
This type template defines a compile-time boolean constant value which can be used to determine whether a type T is a matrix type. For matrix types, the mat_traits template can be used to access their elements generically, or to obtain their dimensions and scalar type.
The mat_traits template must be specialized for (user-defined) matrix types in order to enable vector and matrix operations defined in QVM headers for objects of those types.
The matrix operations defined by QVM do not require matrix types to be copyable.
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.
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.
The mat_traits_defaults template is designed to be used as a public base for user-defined specializations of the mat_traits template, to easily define the required members. If it is used, the only member that must be defined by the user in a mat_traits specialization is write_element; the mat_traits_defaults base will define read_element, as well as scalar_type, rows and cols automatically.
Optionally, the user may also define write_element_idx, in which case the mat_traits_defaults base will provide a suitable read_element_idx definition automatically. Otherwise, mat_traits_defaults defines a protected implementation of write_element_idx which may be made publicly available by the deriving mat_traits specialization in case the matrix type for which it is being specialized can not be indexed efficiently. This write_element_idx function is less efficient (using meta-programming), implemented in terms of the required user-defined write_element.
This template is used by QVM whenever it needs to deduce a copyable matrix type of certain dimensions from a single user-supplied function parameter of matrix type. The returned type must have accessible copy constructor. Note that M itself may be non-copyable.
The main template definition returns an unspecified copyable matrix type of size Rows x Cols, except if mat_traits<M>::rows==Rows && mat_traits<M>::cols==Cols, in which case it returns M, which is suitable only if M is a copyable type. QVM also defines (partial) specializations for the non-copyable matrix types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_mat template is for specifying the preferred matrix type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
The main template definition returns an unspecified matrix type of the requested dimensions with scalar_type obtained by deduce_scalar<A,B>::type, except if A and B are the same matrix type M of dimensions Rows x Cols, in which case M is returned, which is only suitable for copyable types. QVM also defines (partial) specializations for the non-copyable matrix types it produces. Users can define other (partial) specializations for their own types.
A typical use of the deduce_mat2 template is for specifying the preferred matrix type to be returned by the generic function template overloads in QVM depending on the type of their arguments.
QVM defines several class templates (together with appropriate specializations of quat_traits, vec_traits and mat_traits templates) which can be used as generic quaternion, vector and matrix types. Using these types directly wouldn’t be typical though, the main design goal of QVM is to allow users to plug in their own quaternion, vector and matrix types.
This is a simple quaternion type. It converts to any other quaternion type.
The partial specialization of the quat_traits template makes the quat template compatible with the generic operations defined by QVM.
This is a simple vector type. It converts to any other vector type of compatible size.
The partial specialization of the vec_traits template makes the vec template compatible with the generic operations defined by QVM.
This is a simple matrix type. It converts to any other matrix type of compatible size.
The partial specialization of the mat_traits template makes the mat template compatible with the generic operations defined by QVM.
multiplies the scalar component of q by the scalar 42.
multiplies the vector component of q by the scalar 42.
The X, Y and Z elements of the vector component can also be accessed directly using X(q), Y(q) and Z(q).
The return types are lvalues.
can be used to multiply the element at index 1 (indexing in QVM is always zero-based) of a vector v by 42.
The above will leave the Z and W elements of v unchanged but assign the Y element of v2 to the X element of v and the X element of v2 to the Y element of v.
All permutations of X, Y, Z, W, 0, 1 for 2D, 3D and 4D swizzling are available (if the first character of the swizzle identifier is 0 or 1, it is preceded by a _, for example _11XY).
It is valid to use the same vector element more than once: the expression ZZZ(v) is a 3D vector whose X, Y and Z elements all refer to the Z element of v.
Finally, scalars can be "swizzled" to access them as vectors: the expression _0X01(42.0f) is a 4D vector with X=0, Y=42.0, Z=0, W=1.
can be used to multiply the element at row 4 and column 2 of a matrix m by 42.
Copies all elements of the quaternion b to the quaternion a.
The second overload assumes that m is an orthonormal rotation matrix and converts it to a quaternion that performs the same rotation.
Subtracts the elements of b from the corresponding elements of a.
A quaternion of the negated elements of a.
The deduce_quat template can be specialized to deduce the desired return type from the type A.
A quaternion with elements equal to the elements of b subtracted from the corresponding elements of a.
The deduce_quat2 template can be specialized to deduce the desired return type, given the types A and B.
Adds the elements of b to the corresponding elements of a.
A quaternion with elements equal to the elements of a added to the corresponding elements of b.
This operation divides a quaternion by a scalar.
A quaternion that is the result of dividing the quaternion a by the scalar b.
This operation multiplies the quaternion a by the scalar b.
A quaternion that is the result of multiplying the quaternion a by the scalar b.
The result of multiplying the quaternions a and b.
Similar to operator==, except that it uses the binary predicate pred to compare the individual quaternion elements.
The squared magnitude of the quaternion a.
The magnitude of the quaternion a.
If the magnitude of a is zero, throws zero_magnitude_error.
The dot product of the quaternions a and b.
The deduce_scalar template can be specialized to deduce the desired return type, given the types A and B.
Computes the conjugate of a.
Computes the multiplicative inverse of a, or the conjugate-to-norm ratio.
If a is known to be unit length, conjugate is equivalent to inverse, yet it is faster to compute.
A quaternion that is the result of Spherical Linear Interpolation of the quaternions a and b and the interpolation parameter c. When slerp is applied to unit quaternions, the quaternion path maps to a path through 3D rotations in a standard way. The effect is a rotation with uniform angular velocity around a fixed rotation axis.
A read-only quaternion of unspecified type with scalar_type T, with all elements equal to scalar_traits<T>::value(0).
An identity quaternion with scalar type S.
A quaternion of unspecified type which performs a rotation around the axis at angle radians.
In case the axis vector has zero magnitude, throws zero_magnitude_error.
The rot_quat function is not a view proxy; it returns a temp object.
As if: a *= rot_quat(axis,angle).
A view proxy quaternion of unspecified type and scalar type Angle, which performs a rotation around the X axis at angle radians.
As if: a *= rotx_quat(angle).
A view proxy quaternion of unspecified type and scalar type Angle, which performs a rotation around the Y axis at angle radians.
As if: a *= roty_quat(angle).
A view proxy quaternion of unspecified type and scalar type Angle, which performs a rotation around the Z axis at angle radians.
As if: a *= rotz_quat(angle).
A read-only view proxy of a that looks like a quaternion of the same dimensions as a, but with scalar_type Scalar and elements constructed from the corresponding elements of a.
An identity view proxy of a; that is, it simply accesses the elements of a.
qref allows calling QVM operations when a is of built-in type, for example a plain old C array.
Copies all elements of the vector b to the vector a.
A vector of the negated elements of a.
The deduce_vec template can be specialized to deduce the desired return type from the type A.
A vector of the same size as a and b, with elements the elements of b subtracted from the corresponding elements of a.
The deduce_vec2 template can be specialized to deduce the desired return type, given the types A and B.
A vector of the same size as a and b, with elements the elements of b added to the corresponding elements of a.
This operation divides a vector by a scalar.
A vector that is the result of dividing the vector a by the scalar b.
This operation multiplies the vector a by the scalar b.
A vector that is the result of multiplying the vector a by the scalar b.
Similar to operator==, except that the individual elements of a and b are passed to the binary predicate pred for comparison.
The squared magnitude of the vector a.
The magnitude of the vector a.
The dot product of the vectors a and b.
A read-only vector of unspecified type with scalar_type T and size S, with all elements equal to scalar_traits<T>::value(0).
A read-only view proxy of a that looks like a vector of the same dimensions as a, but with scalar_type Scalar and elements constructed from the corresponding elements of a.
vref allows calling QVM operations when a is of built-in type, for example a plain old C array.
Copies all elements of the matrix b to the matrix a.
A matrix of the negated elements of a.
The deduce_mat template can be specialized to deduce the desired return type from the type A.
A matrix of the same size as a and b, with elements the elements of b subtracted from the corresponding elements of a.
The deduce_mat2 template can be specialized to deduce the desired return type, given the types A and B.
A matrix of the same size as a and b, with elements the elements of b added to the corresponding elements of a.
This operation divides a matrix by a scalar.
A matrix that is the result of dividing the matrix a by the scalar b.
This operation multiplies the matrix a matrix by the scalar b.
The result of multiplying the matrices a and b.
A matrix that is the result of multiplying the matrix a by the scalar b.
!( a == b ).
Both overloads compute the inverse of a. The first overload takes the pre-computed determinant of a.
The second overload computes the determinant automatically and throws zero_determinant_error if the computed determinant is zero.
A read-only matrix of unspecified type with scalar_type T, R rows and C columns (or D rows and D columns), with all elements equal to scalar_traits<T>::value(0).
An identity matrix of size D x D and scalar type S.
A matrix of unspecified type, of Dim rows and Dim columns parameter, which performs a rotation around the axis at angle radians, or Tait–Bryan angles (x-y-z, y-z-x, z-x-y, x-z-y, z-y-x, y-x-z), or proper Euler angles (z-x-z, x-y-x, y-z-y, z-y-z, x-z-x, y-x-y). See Euler angles.
These functions are not view proxies; they return a temp object.
Assigns the return value of the corresponding rot_mat function to a.
Multiplies the matrix a in-place by the return value of the corresponding rot_mat function.
A view proxy matrix of unspecified type, of Dim rows and Dim columns and scalar type Angle, which performs a rotation around the X axis at angle radians.
As if: a *= rotx_mat<mat_traits<A>::rows>(angle).
A view proxy matrix of unspecified type, of Dim rows and Dim columns and scalar type Angle, which performs a rotation around the Y axis at angle radians.
As if: a *= roty_mat<mat_traits<A>::rows>(angle).
A view proxy matrix of unspecified type, of Dim rows and Dim columns and scalar type Angle, which performs a rotation around the Z axis at angle radians.
As if: a *= rotz_mat<mat_traits<A>::rows>(angle).
This function computes the determinant of the square matrix a.
where ys = cot(fov_y/2) and xs = ys/aspect.
where ys = cot(fov_y/2), and xs = ys/aspect.
A read-only view proxy of a that looks like a matrix of the same dimensions as a, but with scalar_type Scalar and elements constructed from the corresponding elements of a.
mref allows calling QVM operations when a is of built-in type, for example a plain old C array.
The result of transforming the vector b by the quaternion a.
The result of multiplying the matrix a and the vector b, where b is interpreted as a matrix-column. The resulting matrix-row is returned as a vector type.
As if: return a * XYZ0(b).
As if: return a * XYZ1(b).
The expression del_row<R>(m) returns an lvalue view proxy that looks like the matrix m with row R deleted.
The expression del_col<C>(m) returns an lvalue view proxy that looks like the matrix m with column C deleted.
The expression del_row_col<R,C>(m) returns an lvalue view proxy that looks like the matrix m with row R and column C deleted.
The expression neg_row<R>(m) returns a read-only view proxy that looks like the matrix m with row R negated.
The expression `neg_col<C>(m)` returns a read-only <<view_proxy,`view proxy`>> that looks like the matrix `m` with column `C` negated.
The expression swap_rows<R1,R2>(m) returns an lvalue view proxy that looks like the matrix m with rows R1 and R2 swapped.
The expression swap_cols<C1,C2>(m) returns an lvalue view proxy that looks like the matrix m with columns C1 and C2 swapped.
The expression transposed(m) returns an lvalue view proxy that transposes the matrix m.
The expression col_mat(v) returns an lvalue view proxy that accesses the vector v as a matrix-column.
The expression row_mat(v) returns an lvalue view proxy that accesses the vector v as a matrix-row.
The expression translation_mat(v) returns an lvalue view proxy that accesses the vector v as translation matrix of size 1 + vec_traits<A>::dim.
The expression diag_mat(v) returns an lvalue view proxy that accesses the vector v as a square matrix of the same dimensions in which the elements of v appear as the main diagonal and all other elements are zero.
If v is a 3D vector, the expression diag_mat(XYZ1(v)) can be used as a scaling 4D matrix.
The expression col<C>(m) returns an lvalue view proxy that accesses column C of the matrix m as a vector.
The expression row<R>(m) returns an lvalue view proxy that accesses row R of the matrix m as a vector.
The expression diag(m) returns an lvalue view proxy that accesses the main diagonal of the matrix m as a vector.
The expression translation(m) returns an lvalue view proxy that accesses the translation component of the square matrix m, which is a vector of size D-1, where D is the size of m.
This is the base for all exceptions thorwn by QVM.
This exception indicates that an operation requires a vector or a quaternion with non-zero magnitude, but the computed magnitude is zero.
This exception indicates that an operation requires a matrix with non-zero determinant, but the computed determinant is zero.
This macro is not used directly by QVM, except as the default value of other macros from <boost/qvm/inline.hpp>. A user-defined BOOST_QVM_INLINE should expand to a value that is valid substitution of the inline keyword in function definitions.
This macro is not used directly by QVM, except as the default value of other macros from <boost/qvm/inline.hpp>. A user-defined BOOST_QVM_FORCE_INLINE should expand to a value that is valid substitution of the inline keyword in function definitions, to indicate that the compiler must inline the function. Of course, actual inlining may or may not occur.
QVM uses BOOST_QVM_INLINE_TRIVIAL in definitions of functions that are not critical for the overall performance of the library but are extremely simple (such as one-liners) and therefore should always be inlined.
QVM uses BOOST_QVM_INLINE_CRITICAL in definitions of functions that are critical for the overall performance of the library, such as functions that access individual vector and matrix elements.
QVM uses BOOST_QVM_INLINE_OPERATIONS in definitions of functions that implement various high-level operations, such as matrix multiplication, computing the magnitude of a vector, etc.
QVM uses BOOST_QVM_INLINE_RECURSION in definitions of recursive functions that are not critical for the overall performance of the library (definitions of all critical functions, including critical recursive functions, use BOOST_QVM_INLINE_CRITICAL).
This is the macro QVM uses to assert on precondition violations and logic errors. A user-defined BOOST_QVM_ASSERT should have the semantics of the standard assert.
All static assertions in QVM use the BOOST_QVM_STATIC_ASSERT macro.
C++ is ideal for 3D graphics and other domains that require 3D transformations: define vector and matrix types and then overload the appropriate operators to implement the standard algebraic operations. Because this is relatively straight-forward, there are many libraries that do this, each providing custom vector and matrix types, and then defining the same operations (e.g. matrix multiply) for these types.
Often these libraries are part of a higher level system. For example, video game programmers typically use one set of vector/matrix types with the rendering engine, and another with the physics simulation engine.
QVM proides interoperability between all these different types and APIs by decoupling the standard algebraic functions from the types they operate on — without compromising type safety. The operations work on any type for which proper traits have been specialized. Using QVM, there is no need to translate between the different quaternion, vector or matrix types; they can be mixed in the same expression safely and efficiently.
This design enables QVM to generate types and adaptors at compile time, compatible with any other QVM or user-defined type. For example, transposing a matrix needs not store the result: rather than modifying its argument or returning a new object, it simply binds the original matrix object through a generated type which remaps element access on the fly.
In addition, QVM can be helpful in selectively optimizing individual types or operations for maximum performance where that matters. For example, users can overload a specific operation for specific types, or define highly optimized, possibly platform-specific or for some reason cumbersome to use types, then mix and match them with more user-friendly types in parts of the program where performance isn’t critical.
While QVM defines generic functions that operate on matrix and vector types of arbitrary static dimensions, it also provides a code generator that can be used to create compatible header files that define much simpler specializations of these functions for specific dimensions. This is useful during debugging since the generated code is much easier to read than the template metaprogramming-heavy generic implementations. It is also potentially friendlier to the optimizer.
Any such generated headers must be included before the corresponding generic header file is included. For example, if one creates a header boost/qvm/gen/m5.hpp, it must be included before boost/qvm/mat_operations.hpp in included. However, the generic headers (boost/qvm/mat_operations.hpp, boost/qvm/vec_operations.hpp, boost/qvm/vec_mat_operations.hpp and boost/qvm/swizzle.hpp) already include the generated headers from the list above, so the generated headers don’t need to be included manually.
headers under boost/qvm/gen are not part of the public interface of QVM. For example, boost/qvm/gen/mat_operations2.hpp should not be included directly; #include <boost/qvm/mat_operations2.hpp> instead.
auto tr = transposed(m); //Error: the return type of transposed can not be copied.
Many view proxies are not read-only, that is, they’re lvalues; changes made on the view proxy operate on the original object. This is another reason why they can not be captured by value with auto.
QVM does not call standard math functions (e.g. sin, cos, etc.) directly. Instead, it calls function templates declared in boost/qvm/math.hpp in namespace boost::qvm. This allows the user to specialize these templates for user-defined scalar types.
QVM itself defines specializations of the math function templates only for float and double, but it does not provide generic definitions. This is done to protect the user from unintentionally writing code that binds standard math functions that take double when passing arguments of lesser types, which would be suboptimal.
Because of this, a call to e.g. rot_mat(axis,1) will compile successfully but fail to link, since it calls e.g. boost::qvm::sin<int>, which is undefined. Because rotations by integer number of radians are rarely needed, in QVM there is no protection against such errors. In such cases the solution is to use rot_mat(axis,1.0f) instead.
QVM is part of Boost and is distributed under the Boost Software License, Version 1.0.
The source code is available in QVM GitHub repository.
© 2008-2018 Emil Dotchevski and Reverge Studios, Inc.
See the QVM Travis CI Builds.
Please use the Boost Developers mailing list.
What is the motivation behind QVM? Why not just use uBLAS/Eigen/CML/GLM/etc?
The primary domain of QVM is realtime graphics and simulation applications, so it is not a complete linear algebra library. While (naturally) there is some overlap with such libraries, QVM puts the emphasis on 2, 3 and 4 dimensional zero-overhead operations (hence domain-specific features like Swizzling).
How does the qvm::vec (or qvm::mat, or qvm::quat) template compare to vector types from other libraries?
The qvm::vec template is not in any way central to the vector operations defined by QVM. The operations are designed to work with any user-defined vector type or with 3rd-party vector types (e.g. D3DVECTOR), while the qvm::vec template is simply a default return type for expressions that use arguments of different types that would be incompatible outside of QVM. For example, if the deduce_mat2 hasn’t been specialized, calling cross with a user-defined type vec3 and a user-defined type float3 returns a qvm::vec.
Why doesn’t QVM use  or () to access vector and matrix elements?
Because it’s designed to work with user-defined types, and the C++ standard requires these operators to be members. Of course if a user-defined type defines operator or operator() they are available for use with other QVM functions, but QVM defines its own mechanisms for accessing quaternion elements, accessing vector elements (as well as swizzling), and accessing matrix elements.

References: v.

 v.

 v.

 v.

 v.

 v.