1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8"> 5<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--> 6<meta name="viewport" content="width=device-width, initial-scale=1.0"> 7<meta name="generator" content="Asciidoctor 1.5.8"> 8<meta name="author" content="Quaternion / Vector / Matrix Library for C++-11 | Emil Dotchevski"> 9<title>QVM</title> 10<link rel="stylesheet" href="./zajo-dark.css"> 11<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> 12<meta name="keywords" content="c++,quaternion,vector,matrix,open source"> 13<meta name="description" content="Generic C++ library for working with Quaternions, Vectors and Matrices"> 14<link rel="stylesheet" href="./zajo-light.css" disabled=true> 15<script> 16function switch_style() 17{ 18 var i, tag; 19 for( i=0, tag=document.getElementsByTagName("link"); i<tag.length; i++ ) 20 if( tag[i].rel.indexOf("stylesheet")!=-1 && tag[i].href.includes("zajo-") ) 21 tag[i].disabled = !tag[i].disabled; 22} 23</script> 24</head> 25<body class="article toc2 toc-left"> 26<div id="header"> 27<h1>QVM <a href="https://ci.appveyor.com/project/zajo/qvm"><img style="margin-left:8px; margin-top:21px; float:right; vertical-align: top" src="https://ci.appveyor.com/api/projects/status/rphx1liilphuk1t5?svg=true"></a> <a href="https://travis-ci.org/boostorg/qvm"><img style="margin-top:21px; float:right; vertical-align: top" src="https://travis-ci.org/boostorg/qvm.svg?branch=master"></a><div style="z-index: 3; bottom:-16px; right:4px; position:fixed"><input width="32" height="32" type="image" alt="Skin" src="./skin.png" onclick="this.blur();switch_style();return false;"/></div></h1> 28<div class="details"> 29<span id="author" class="author">Quaternion / Vector / Matrix Library for C++-11 | Emil Dotchevski</span><br> 30</div> 31<div id="toc" class="toc2"> 32<div id="toctitle"></div> 33<ul class="sectlevel1"> 34<li><a href="#_abstract">Abstract</a></li> 35<li><a href="#tutorial">Tutorial</a> 36<ul class="sectlevel2"> 37<li><a href="#_quaternions_vectors_matrices">Quaternions, Vectors, Matrices</a></li> 38<li><a href="#_c_arrays">C Arrays</a></li> 39<li><a href="#view_proxy">View proxies</a></li> 40<li><a href="#_swizzling">Swizzling</a></li> 41<li><a href="#enable_if">SFINAE/enable_if</a></li> 42<li><a href="#_interoperability">Interoperability</a> 43<ul class="sectlevel3"> 44<li><a href="#_specifying_return_types_for_binary_operations">Specifying return types for binary operations</a></li> 45<li><a href="#_specifying_return_types_for_unary_operations">Specifying return types for unary operations</a></li> 46<li><a href="#_converting_between_different_quaternion_vector_and_matrix_types">Converting between different quaternion, vector and matrix types</a></li> 47</ul> 48</li> 49</ul> 50</li> 51<li><a href="#reference">Reference</a> 52<ul class="sectlevel2"> 53<li><a href="#_header_files">Header Files</a></li> 54<li><a href="#type_traits">Type Traits System</a> 55<ul class="sectlevel3"> 56<li><a href="#scalar_requirements">Scalar Requirements</a></li> 57<li><a href="#is_scalar"><code>is_scalar</code></a></li> 58<li><a href="#scalar_traits"><code>scalar_traits</code></a></li> 59<li><a href="#deduce_scalar"><code>deduce_scalar</code></a></li> 60<li><a href="#scalar"><code>scalar</code></a></li> 61<li><a href="#is_quat"><code>is_quat</code></a></li> 62<li><a href="#quat_traits"><code>quat_traits</code></a></li> 63<li><a href="#quat_traits_defaults"><code>quat_traits_defaults</code></a></li> 64<li><a href="#deduce_quat"><code>deduce_quat</code></a></li> 65<li><a href="#deduce_quat2"><code>deduce_quat2</code></a></li> 66<li><a href="#is_vec"><code>is_vec</code></a></li> 67<li><a href="#vec_traits"><code>vec_traits</code></a></li> 68<li><a href="#vec_traits_defaults"><code>vec_traits_defaults</code></a></li> 69<li><a href="#deduce_vec"><code>deduce_vec</code></a></li> 70<li><a href="#deduce_vec2"><code>deduce_vec2</code></a></li> 71<li><a href="#is_mat"><code>is_mat</code></a></li> 72<li><a href="#mat_traits"><code>mat_traits</code></a></li> 73<li><a href="#mat_traits_defaults"><code>mat_traits_defaults</code></a></li> 74<li><a href="#deduce_mat"><code>deduce_mat</code></a></li> 75<li><a href="#deduce_mat2"><code>deduce_mat2</code></a></li> 76</ul> 77</li> 78<li><a href="#_built_in_quaternion_vector_and_matrix_types">Built-in Quaternion, Vector and Matrix Types</a> 79<ul class="sectlevel3"> 80<li><a href="#quat"><code>quat</code></a></li> 81<li><a href="#vec"><code>vec</code></a></li> 82<li><a href="#mat"><code>mat</code></a></li> 83</ul> 84</li> 85<li><a href="#_element_access">Element Access</a> 86<ul class="sectlevel3"> 87<li><a href="#quat_access">Quaternions</a></li> 88<li><a href="#vec_access">Vectors</a></li> 89<li><a href="#swizzling">Vector Element Swizzling</a></li> 90<li><a href="#mat_access">Matrices</a></li> 91</ul> 92</li> 93<li><a href="#_quaternion_operations">Quaternion Operations</a> 94<ul class="sectlevel3"> 95<li><a href="#quat_assign"><code>assign</code></a></li> 96<li><a href="#quat_convert_to"><code>convert_to</code></a></li> 97<li><a href="#quat_minus_eq"><code>operator-=</code></a></li> 98<li><a href="#quat_minus_unary"><code>operator-</code> (unary)</a></li> 99<li><a href="#quat_minus"><code>operator-</code> (binary)</a></li> 100<li><a href="#quat_plus_eq"><code>operator+=</code></a></li> 101<li><a href="#quat_plus"><code>operator+</code></a></li> 102<li><a href="#quat_div_eq_scalar"><code>operator/=</code> (scalar)</a></li> 103<li><a href="#quat_div_scalar"><code>operator/</code> (scalar)</a></li> 104<li><a href="#quat_mul_eq_scalar"><code>operator*=</code> (scalar)</a></li> 105<li><a href="#quat_mul_eq"><code>operator*=</code></a></li> 106<li><a href="#quat_mul_scalar"><code>operator*</code> (scalar)</a></li> 107<li><a href="#quat_mul"><code>operator*</code></a></li> 108<li><a href="#quat_eq"><code>operator==</code></a></li> 109<li><a href="#quat_neq"><code>operator!=</code></a></li> 110<li><a href="#quat_cmp"><code>cmp</code></a></li> 111<li><a href="#quat_mag_sqr"><code>mag_sqr</code></a></li> 112<li><a href="#quat_mag"><code>mag</code></a></li> 113<li><a href="#quat_normalized"><code>normalized</code></a></li> 114<li><a href="#quat_normalize"><code>normalize</code></a></li> 115<li><a href="#quat_dot"><code>dot</code></a></li> 116<li><a href="#conjugate"><code>conjugate</code></a></li> 117<li><a href="#quat_inverse"><code>inverse</code></a></li> 118<li><a href="#slerp"><code>slerp</code></a></li> 119<li><a href="#zero_quat"><code>zero_quat</code></a></li> 120<li><a href="#quat_set_zero"><code>set_zero</code></a></li> 121<li><a href="#identity_quat"><code>identity_quat</code></a></li> 122<li><a href="#quat_set_identity"><code>set_identity</code></a></li> 123<li><a href="#rot_quat"><code>rot_quat</code></a></li> 124<li><a href="#quat_set_rot"><code>set_rot</code></a></li> 125<li><a href="#quat_rotate"><code>rotate</code></a></li> 126<li><a href="#rotx_quat"><code>rotx_quat</code></a></li> 127<li><a href="#quat_set_rotx"><code>set_rotx</code></a></li> 128<li><a href="#quat_rotate_x"><code>rotate_x</code></a></li> 129<li><a href="#roty_quat"><code>roty_quat</code></a></li> 130<li><a href="#quat_set_roty"><code>set_roty</code></a></li> 131<li><a href="#quat_rotate_y"><code>rotate_y</code></a></li> 132<li><a href="#rotz_quat"><code>rotz_quat</code></a></li> 133<li><a href="#quat_set_rotz"><code>set_rotz</code></a></li> 134<li><a href="#quat_rotate_z"><code>rotate_z</code></a></li> 135<li><a href="#quat_scalar_cast"><code>scalar_cast</code></a></li> 136<li><a href="#qref"><code>qref</code></a></li> 137</ul> 138</li> 139<li><a href="#_vector_operations">Vector Operations</a> 140<ul class="sectlevel3"> 141<li><a href="#vec_assign"><code>assign</code></a></li> 142<li><a href="#vec_convert_to"><code>convert_to</code></a></li> 143<li><a href="#vec_minus_eq"><code>operator-=</code></a></li> 144<li><a href="#vec_minus_unary"><code>operator-</code> (unary)</a></li> 145<li><a href="#vec_minus"><code>operator-</code> (binary)</a></li> 146<li><a href="#vec_plus_eq"><code>operator+=</code></a></li> 147<li><a href="#vec_plus"><code>operator+</code></a></li> 148<li><a href="#vec_div_eq_scalar"><code>operator/=</code> (scalar)</a></li> 149<li><a href="#vec_div_scalar"><code>operator/</code></a></li> 150<li><a href="#vec_mul_eq_scalar"><code>operator*=</code></a></li> 151<li><a href="#vec_mul_scalar"><code>operator*</code></a></li> 152<li><a href="#vec_eq"><code>operator==</code></a></li> 153<li><a href="#vec_neq"><code>operator!=</code></a></li> 154<li><a href="#vec_cmp"><code>cmp</code></a></li> 155<li><a href="#vec_mag_sqr"><code>mag_sqr</code></a></li> 156<li><a href="#vec_mag"><code>mag</code></a></li> 157<li><a href="#vec_normalized"><code>normalized</code></a></li> 158<li><a href="#vec_normalize"><code>normalize</code></a></li> 159<li><a href="#vec_dot"><code>dot</code></a></li> 160<li><a href="#vec_cross"><code>cross</code></a></li> 161<li><a href="#zero_vec"><code>zero_vec</code></a></li> 162<li><a href="#vec_set_zero"><code>set_zero</code></a></li> 163<li><a href="#vec_scalar_cast"><code>scalar_cast</code></a></li> 164<li><a href="#vref"><code>vref</code></a></li> 165</ul> 166</li> 167<li><a href="#_matrix_operations">Matrix Operations</a> 168<ul class="sectlevel3"> 169<li><a href="#mat_assign"><code>assign</code></a></li> 170<li><a href="#mat_convert_to"><code>convert_to</code></a></li> 171<li><a href="#mat_minus_eq_scalar"><code>operator-=</code></a></li> 172<li><a href="#mat_minus_unary"><code>operator-</code> (unary)</a></li> 173<li><a href="#mat_minus"><code>operator-</code></a></li> 174<li><a href="#mat_plus_eq_scalar"><code>operator+=</code></a></li> 175<li><a href="#mat_plus"><code>operator+</code></a></li> 176<li><a href="#mat_div_eq_scalar"><code>operator/=</code> (scalar)</a></li> 177<li><a href="#mat_div_scalar"><code>operator/</code> (scalar)</a></li> 178<li><a href="#mat_mul_eq"><code>operator*=</code></a></li> 179<li><a href="#mat_mul_eq_scalar"><code>operator*=</code> (scalar)</a></li> 180<li><a href="#mat_mul"><code>operator*</code></a></li> 181<li><a href="#mat_mul_scalar"><code>operator*</code> (scalar)</a></li> 182<li><a href="#mat_eq"><code>operator==</code></a></li> 183<li><a href="#mat_neq"><code>operator!=</code></a></li> 184<li><a href="#mat_cmp"><code>cmp</code></a></li> 185<li><a href="#mat_inverse"><code>inverse</code></a></li> 186<li><a href="#zero_mat"><code>zero_mat</code></a></li> 187<li><a href="#mat_set_zero"><code>set_zero</code></a></li> 188<li><a href="#identity_mat"><code>identity_mat</code></a></li> 189<li><a href="#mat_set_identity"><code>set_identity</code></a></li> 190<li><a href="#rot_mat"><code>rot_mat</code> / Euler angles</a></li> 191<li><a href="#mat_set_rot"><code>set_rot</code> / Euler angles</a></li> 192<li><a href="#mat_rotate"><code>rotate</code> / Euler angles</a></li> 193<li><a href="#rotx_mat"><code>rotx_mat</code></a></li> 194<li><a href="#mat_set_rotx"><code>set_rotx</code></a></li> 195<li><a href="#mat_rotate_x"><code>rotate_x</code></a></li> 196<li><a href="#roty_mat"><code>roty_mat</code></a></li> 197<li><a href="#mat_set_roty"><code>set_roty</code></a></li> 198<li><a href="#mat_rotate_y"><code>rotate_y</code></a></li> 199<li><a href="#rotz_mat"><code>rotz_mat</code></a></li> 200<li><a href="#mat_set_rotz"><code>set_rotz</code></a></li> 201<li><a href="#mat_rotate_z"><code>rotate_z</code></a></li> 202<li><a href="#determinant"><code>determinant</code></a></li> 203<li><a href="#perspective_lh"><code>perspective_lh</code></a></li> 204<li><a href="#perspective_rh"><code>perspective_rh</code></a></li> 205<li><a href="#mat_scalar_cast"><code>scalar_cast</code></a></li> 206<li><a href="#mref"><code>mref</code></a></li> 207</ul> 208</li> 209<li><a href="#_quaternion_vector_operations">Quaternion-Vector Operations</a> 210<ul class="sectlevel3"> 211<li><a href="#quat_vec_mul"><code>operator*</code></a></li> 212</ul> 213</li> 214<li><a href="#_matrix_vector_operations">Matrix-Vector Operations</a> 215<ul class="sectlevel3"> 216<li><a href="#mat_vec_mul"><code>operator*</code></a></li> 217<li><a href="#transform_vector"><code>transform_vector</code></a></li> 218<li><a href="#transform_point"><code>transform_point</code></a></li> 219</ul> 220</li> 221<li><a href="#_matrix_to_matrix_view_proxies">Matrix-to-Matrix View Proxies</a> 222<ul class="sectlevel3"> 223<li><a href="#del_row"><code>del_row</code></a></li> 224<li><a href="#del_col"><code>del_col</code></a></li> 225<li><a href="#del_row_col"><code>del_row_col</code></a></li> 226<li><a href="#neg_row"><code>neg_row</code></a></li> 227<li><a href="#neg_col"><code>neg_col</code></a></li> 228<li><a href="#swap_rows"><code>swap_rows</code></a></li> 229<li><a href="#swap_cols"><code>swap_cols</code></a></li> 230<li><a href="#transposed"><code>transposed</code></a></li> 231</ul> 232</li> 233<li><a href="#_vector_to_matrix_view_proxies">Vector-to-Matrix View Proxies</a> 234<ul class="sectlevel3"> 235<li><a href="#col_mat"><code>col_mat</code></a></li> 236<li><a href="#row_mat"><code>row_mat</code></a></li> 237<li><a href="#translation_mat"><code>translation_mat</code></a></li> 238<li><a href="#diag_mat"><code>diag_mat</code></a></li> 239</ul> 240</li> 241<li><a href="#_matrix_to_vector_view_proxies">Matrix-to-Vector View Proxies</a> 242<ul class="sectlevel3"> 243<li><a href="#col"><code>col</code></a></li> 244<li><a href="#row"><code>row</code></a></li> 245<li><a href="#diag"><code>diag</code></a></li> 246<li><a href="#translation"><code>translation</code></a></li> 247</ul> 248</li> 249<li><a href="#_exceptions">Exceptions</a> 250<ul class="sectlevel3"> 251<li><a href="#error"><code>error</code></a></li> 252<li><a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a></li> 253<li><a href="#zero_determinant_error"><code>zero_determinant_error</code></a></li> 254</ul> 255</li> 256<li><a href="#_macros_and_configuration_boost_qvm">Macros and Configuration: BOOST_QVM_</a> 257<ul class="sectlevel3"> 258<li><a href="#BOOST_QVM_INLINE"><code>INLINE</code></a></li> 259<li><a href="#BOOST_QVM_FORCE_INLINE"><code>FORCE_INLINE</code></a></li> 260<li><a href="#BOOST_QVM_INLINE_TRIVIAL"><code>INLINE_TRIVIAL</code></a></li> 261<li><a href="#BOOST_QVM_INLINE_CRITICAL"><code>INLINE_CRITICAL</code></a></li> 262<li><a href="#BOOST_QVM_INLINE_OPERATIONS"><code>INLINE_OPERATIONS</code></a></li> 263<li><a href="#BOOST_QVM_INLINE_RECURSION"><code>INLINE_RECURSION</code></a></li> 264<li><a href="#BOOST_QVM_ASSERT"><code>ASSERT</code></a></li> 265<li><a href="#BOOST_QVM_STATIC_ASSERT"><code>STATIC_ASSERT</code></a></li> 266<li><a href="#BOOST_QVM_THROW_EXCEPTION"><code>THROW_EXCEPTION</code></a></li> 267</ul> 268</li> 269</ul> 270</li> 271<li><a href="#rationale">Design Rationale</a></li> 272<li><a href="#_code_generator">Code Generator</a></li> 273<li><a href="#_known_quirks_and_issues">Known Quirks and Issues</a> 274<ul class="sectlevel2"> 275<li><a href="#_capturing_view_proxies_with_auto">Capturing View Proxies with <code>auto</code></a></li> 276<li><a href="#_binding_qvm_overloads_from_an_unrelated_namespace">Binding QVM Overloads From an Unrelated Namespace</a></li> 277<li><a href="#_link_errors_when_calling_math_functions_with_int_arguments">Link Errors When Calling Math Functions with <code>int</code> Arguments</a></li> 278</ul> 279</li> 280<li><a href="#_distribution">Distribution</a></li> 281<li><a href="#_portability">Portability</a></li> 282<li><a href="#_feedback_support">Feedback / Support</a></li> 283<li><a href="#_qa">Q&A</a></li> 284</ul> 285</div> 286</div> 287<div id="content"> 288<div id="preamble"> 289<div class="sectionbody"> 290<div class="paragraph text-right"> 291<p><a href="https://github.com/boostorg/qvm">GitHub</a> | <a href="./qvm.pdf">PDF</a></p> 292</div> 293</div> 294</div> 295<div class="sect1"> 296<h2 id="_abstract">Abstract</h2> 297<div class="sectionbody"> 298<div class="paragraph"> 299<p>QVM is a generic library for working with Quaternions, Vectors and Matrices of static size. Features:</p> 300</div> 301<div class="exampleblock"> 302<div class="content"> 303<div class="ulist"> 304<ul> 305<li> 306<p>Emphasis on 2, 3 and 4-dimensional operations needed in graphics, video games and simulation applications.</p> 307</li> 308<li> 309<p>Free function templates operate on any compatible user-defined quaternion, vector or matrix type.</p> 310</li> 311<li> 312<p>Quaternion, vector and matrix types from different libraries or subsystems can be safely mixed in the same expression.</p> 313</li> 314<li> 315<p>Type-safe mapping between compatible lvalue types with no temporary objects; e.g. transpose remaps the elements, rather than transforming the matrix.</p> 316</li> 317</ul> 318</div> 319</div> 320</div> 321<div class="paragraph text-right"> 322<p><a href="#tutorial">Tutorial</a> | <a href="#reference">Reference</a> | <a href="#rationale">Design Rationale</a></p> 323</div> 324</div> 325</div> 326<div class="sect1"> 327<h2 id="tutorial">Tutorial</h2> 328<div class="sectionbody"> 329<div class="sect2"> 330<h3 id="_quaternions_vectors_matrices">Quaternions, Vectors, Matrices</h3> 331<div class="paragraph"> 332<p>Out of the box QVM defines generic yet simple <a href="#quat"><code>quat</code></a>, <a href="#vec"><code>vec</code></a> and <a href="#mat"><code>mat</code></a> types. For example, the following snippet creates a quaternion object that rotates around the X axis:</p> 333</div> 334<div class="listingblock"> 335<div class="content"> 336<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">quat<float> rx = rotx_quat(3.14159f);</code></pre> 337</div> 338</div> 339<div class="paragraph"> 340<p>Similarly, a matrix that translates by a given vector can be created as follows:</p> 341</div> 342<div class="listingblock"> 343<div class="content"> 344<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">vec<float,3> v = {0,0,7}; 345mat<float,4,4> tr = translation_mat(v);</code></pre> 346</div> 347</div> 348<div class="paragraph"> 349<p>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 <a href="#quat_traits"><code>quat_traits</code></a>, <a href="#vec_traits"><code>vec_traits</code></a> and <a href="#mat_traits"><code>mat_traits</code></a> templates.</p> 350</div> 351<div class="paragraph"> 352<p>For example, a user-defined 3D vector type <code>float3</code> can be introduced to QVM as follows:</p> 353</div> 354<div class="listingblock"> 355<div class="content"> 356<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">struct float3 { float a[3]; }; 357 358namespace boost { namespace qvm { 359 360 template <> 361 struct vec_traits<float3> { 362 363 static int const dim=3; 364 typedef float scalar_type; 365 366 template <int I> 367 static inline scalar_type & write_element( float3 & v ) { 368 return v.a[I]; 369 } 370 371 template <int I> 372 static inline scalar_type read_element( float3 const & v ) { 373 return v.a[I]; 374 } 375 376 static inline scalar_type & write_element_idx( int i, float3 & v ) { 377 return v.a[i]; 378 } //optional 379 380 static inline scalar_type read_element_idx( int i, float3 const & v ) { 381 return v.a[i]; 382 } //optional 383 384 }; 385 386} }</code></pre> 387</div> 388</div> 389<div class="paragraph"> 390<p>Equivalently, using the <a href="#vec_traits_defaults"><code>vec_traits_defaults</code></a> template the above can be shortened to:</p> 391</div> 392<div class="listingblock"> 393<div class="content"> 394<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 395 396 template <> 397 struct vec_traits<float3>: vec_traits_defaults<float3,float,3> { 398 399 template <int I> 400 static inline scalar_type & write_element( float3 & v ) { 401 return v.a[I]; 402 } 403 404 static inline scalar_type & write_element_idx( int i, float3 & v ) { 405 return v.a[i]; 406 } //optional 407 408 }; 409 410} }</code></pre> 411</div> 412</div> 413<div class="paragraph"> 414<p>After a similar specialization of the <a href="#mat_traits"><code>mat_traits</code></a> template for a user-defined 3x3 matrix type <code>float33</code>, the full range of vector and matrix operations defined by QVM headers becomes available automatically:</p> 415</div> 416<div class="listingblock"> 417<div class="content"> 418<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v; 419X(v) = 0; 420Y(v) = 0; 421Z(v) = 7; 422float vmag = mag(v); 423float33 m = rotx_mat<3>(3.14159f); 424float3 vrot = m * v;</code></pre> 425</div> 426</div> 427<div class="paragraph"> 428<p>User-defined quaternion types are similarly introduced to QVM by specializing the <a href="#quat_traits"><code>quat_traits</code></a> template.</p> 429</div> 430<hr> 431</div> 432<div class="sect2"> 433<h3 id="_c_arrays">C Arrays</h3> 434<div class="paragraph"> 435<p>In <a href="#boost/qvm/quat_traits_array.hpp"><code>boost/qvm/quat_traits_array.hpp</code></a>, <a href="#boost/qvm/vec_traits_array.hpp"><code>boost/qvm/vec_traits_array.hpp</code></a> and <a href="#boost/qvm/mat_traits_array.hpp"><code>boost/qvm/mat_traits_array.hpp</code></a> QVM defines appropriate <a href="#quat_traits"><code>quat_traits</code></a>, <a href="#vec_traits"><code>vec_traits</code></a> and <a href="#mat_traits"><code>mat_traits</code></a> specializations that allow QVM functions to operate directly on plain old C arrays:</p> 436</div> 437<div class="listingblock"> 438<div class="content"> 439<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float v[3] = {0,0,7}; 440float3 vrot = rotx_mat<3>(3.14159f) * v;</code></pre> 441</div> 442</div> 443<div class="paragraph"> 444<p>Naturally, operator overloads cannot kick in if all elements of an expression are of built-in types. The following is still illegal:</p> 445</div> 446<div class="listingblock"> 447<div class="content"> 448<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float v[3] = {0,0,7}; 449v *= 42;</code></pre> 450</div> 451</div> 452<div class="paragraph"> 453<p>The <a href="#vref"><code>vref</code></a> and <a href="#mref"><code>mref</code></a> function templates can be used to work around this issue:</p> 454</div> 455<div class="listingblock"> 456<div class="content"> 457<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float v[3] = {0,0,7}; 458vref(v) *= 42;</code></pre> 459</div> 460</div> 461<hr> 462</div> 463<div class="sect2"> 464<h3 id="view_proxy">View proxies</h3> 465<div class="paragraph"> 466<p>QVM defines various function templates that provide static mapping between (possibly user-defined) quaternion, vector and matrix types. The example below multiplies column 1 (QVM indexes are always zero-based) of the matrix <code>m</code> by a scalar:</p> 467</div> 468<div class="listingblock"> 469<div class="content"> 470<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">void multiply_column1( float33 & m, float scalar ) { 471 col<1>(m) *= scalar; 472}</code></pre> 473</div> 474</div> 475<div class="paragraph"> 476<p>The expression <a href="#col"><code>col<1>(m)</code></a> is an lvalue of an unspecified 3D vector type that refers to column 1 of <code>m</code>. Note however that this does not create any temporary objects; instead <code>operator*=</code> above works directly with a reference to <code>m</code>.</p> 477</div> 478<div class="paragraph"> 479<p>Here is another example, multiplying a transposed view of a matrix by a vector of some user-defined type <code>float3</code>:</p> 480</div> 481<div class="listingblock"> 482<div class="content"> 483<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v = {0,0,7}; 484float3 vrot = transposed(rotx_mat<3>(3.14159f)) * v;</code></pre> 485</div> 486</div> 487<div class="paragraph"> 488<p>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.</p> 489</div> 490<hr> 491</div> 492<div class="sect2"> 493<h3 id="_swizzling">Swizzling</h3> 494<div class="paragraph"> 495<p>QVM allows accessing vector elements by swizzling, exposing vector views of different dimensions, and/or views with reordered elements. The example below rotates <code>v</code> around the X axis, and stores the resulting vector back in <code>v</code> but with the X and Y elements swapped:</p> 496</div> 497<div class="listingblock"> 498<div class="content"> 499<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v = {0,0,7}; 500YXZ(v) = rotx_mat<3>(3.14159f) * v;</code></pre> 501</div> 502</div> 503<div class="paragraph"> 504<p>A special case of swizzling provides next-dimension-view of a vector object, adding either 0 or 1 as its last component. Assuming <code>float3</code> is a 3D vector type, and <code>float4</code> is a 4D vector type, the following statements are valid:</p> 505</div> 506<div class="listingblock"> 507<div class="content"> 508<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v = {0,0,7}; 509float4 point = XYZ1(v); //{0,0,7,1} 510float4 vector = XYZ0(v); //{0,0,7,0}</code></pre> 511</div> 512</div> 513<div class="paragraph"> 514<p>It is also valid for swizzling to address vector elements more than once:</p> 515</div> 516<div class="listingblock"> 517<div class="content"> 518<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v = {0,0,7}; 519float4 v1 = ZZZZ(v); //{7,7,7,7}</code></pre> 520</div> 521</div> 522<div class="paragraph"> 523<p>QVM defines all permutations of <code>X</code>, <code>Y</code>, <code>Z</code>, <code>W</code> 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. <code>_1XY</code>).</p> 524</div> 525<div class="paragraph"> 526<p>The swizzling syntax can also be used to bind scalars as vectors. For example:</p> 527</div> 528<div class="listingblock"> 529<div class="content"> 530<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float3 v = _00X(42.0f); //{0,0,42}</code></pre> 531</div> 532</div> 533<hr> 534</div> 535<div class="sect2"> 536<h3 id="enable_if">SFINAE/enable_if</h3> 537<div class="paragraph"> 538<p>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.</p> 539</div> 540<div class="paragraph"> 541<p>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 <code>enable_if</code> library.</p> 542</div> 543<div class="paragraph"> 544<p>For example, QVM defines <code>operator*</code> overload which works with any user-defined matrix and vector types. The naive approach would be to declare this overload as follows:</p> 545</div> 546<div class="listingblock"> 547<div class="content"> 548<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">template <class Matrix,class Vector> 549Vector operator*( Matrix const & m, Vector const & v );</code></pre> 550</div> 551</div> 552<div class="paragraph"> 553<p>Even if the function definition might contain code that would compile only for <code>Matrix</code> and <code>Vector</code> 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.</p> 554</div> 555<div class="paragraph"> 556<p>Using <code>enable_if</code>, QVM declares such overloads in a way that preserves their generic signature but only participate in overload resolutions if the passed parameters make sense depending on the semantics of the operation being defined:</p> 557</div> 558<div class="listingblock"> 559<div class="content"> 560<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">template <class A,class B> 561typename enable_if_c< 562 is_mat<A>::value && is_vec<B>::value && mat_traits<A>::cols==vec_traits<B>::dim, //Condition 563 B>::type //Return type 564operator*( A const & a, B const & b );</code></pre> 565</div> 566</div> 567<div class="paragraph"> 568<p>For brevity, function declarations throughout this documentation specify the condition which controls whether they are enabled or not without specifying exactly what <code>enable_if</code> construct is used to achieve this effect.</p> 569</div> 570<hr> 571</div> 572<div class="sect2"> 573<h3 id="_interoperability">Interoperability</h3> 574<div class="paragraph"> 575<p>An important design goal of QVM is that it works seamlessly with 3rd-party quaternion, vector and matrix types and libraries. Even when such libraries overload the same C++ operators as QVM, it is safe to bring the entire <code>boost::qvm</code> namespace in scope by specifying:</p> 576</div> 577<div class="listingblock"> 578<div class="content"> 579<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">using namespace boost::qvm;</code></pre> 580</div> 581</div> 582<div class="paragraph"> 583<p>The above using directive does not introduce ambiguities with function and operator overloads defined by a 3rd-party library because:</p> 584</div> 585<div class="ulist"> 586<ul> 587<li> 588<p>Most <code>boost::qvm</code> function overloads and all operator overloads use SFINAE/<code>enable_if</code>, which makes them "disappear" unless an expression uses types that have the appropriate QVM-specific type traits defined;</p> 589</li> 590<li> 591<p>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.</p> 592</li> 593</ul> 594</div> 595<div class="admonitionblock note"> 596<table> 597<tr> 598<td class="icon"> 599<i class="fa icon-note" title="Note"></i> 600</td> 601<td class="content"> 602Bringing 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 <code>boost::qvm::sfinae</code> in scope instead, which contains only function and operator overloads that use SFINAE/<code>enable_if</code>. 603</td> 604</tr> 605</table> 606</div> 607<div class="sect3"> 608<h4 id="_specifying_return_types_for_binary_operations">Specifying return types for binary operations</h4> 609<div class="paragraph"> 610<p>Bringing the <code>boost::qvm</code> 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 <code>m1</code> of type <code>user_matrix1</code> by a 3x3 matrix <code>m2</code> of type <code>user_matrix2</code>, what type should that operation return?</p> 611</div> 612<div class="paragraph"> 613<p>The answer is that by default, QVM returns some kind of compatible matrix type, so it is always safe to write:</p> 614</div> 615<div class="listingblock"> 616<div class="content"> 617<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">auto & m = m1 * m2;</code></pre> 618</div> 619</div> 620<div class="paragraph"> 621<p>However, the type deduced by default converts implicitly to any compatible matrix type, so the following is also valid, at the cost of a temporary:</p> 622</div> 623<div class="listingblock"> 624<div class="content"> 625<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">user_matrix1 m = m1 * m2;</code></pre> 626</div> 627</div> 628<div class="paragraph"> 629<p>While the temporary object can be optimized away by many compilers, it can be avoided altogether by specializing the <a href="#deduce_mat2"><code>deduce_mat2</code></a> template. For example, to specify that multiplying a <code>user_matrix1</code> by a <code>user_matrix2</code> should always produce a <code>user_matrix1</code> object, you could write:</p> 630</div> 631<div class="listingblock"> 632<div class="content"> 633<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 634 635 template <> 636 struct deduce_mat2<user_matrix1,user_matrix2,3,3> { 637 typedef user_matrix1 type; 638 }; 639 640 template <> 641 struct deduce_mat2<user_matrix2,user_matrix1,3,3> { 642 typedef user_matrix1 type; 643 }; 644 645} }</code></pre> 646</div> 647</div> 648<div class="admonitionblock warning"> 649<table> 650<tr> 651<td class="icon"> 652<i class="fa icon-warning" title="Warning"></i> 653</td> 654<td class="content"> 655<div class="paragraph"> 656<p>Be mindful of potential ODR violation when using <a href="#deduce_quat2"><code>deduce_quat2</code></a>, <a href="#deduce_vec2"><code>deduce_vec2</code></a> and <a href="#deduce_mat2"><code>deduce_mat2</code></a> in independent libraries. For example, this could happen if <code>lib1</code> defines <code>deduce_vec2<lib1::vec,lib2::vec>::type</code> as <code>lib1::vec</code> and in the same program <code>lib2</code> defines <code>deduce_vec2<lib1::vec,lib2::vec>::type</code> as <code>lib2::vec</code>.</p> 657</div> 658<div class="paragraph"> 659<p>It is best to keep such specializations out of <code>lib1</code> and <code>lib2</code>. Of course, it is always safe for <code>lib1</code> and <code>lib2</code> to use <a href="#convert_to"><code>convert_to</code></a> to convert between the <code>lib1::vec</code> and <code>lib2::vec</code> types as needed.</p> 660</div> 661</td> 662</tr> 663</table> 664</div> 665</div> 666<div class="sect3"> 667<h4 id="_specifying_return_types_for_unary_operations">Specifying return types for unary operations</h4> 668<div class="paragraph"> 669<p>Perhaps surprisingly, unary operations that return an object by value have a similar, though simpler issue. That’s because the argument they’re called with may not be copyable, as in:</p> 670</div> 671<div class="listingblock"> 672<div class="content"> 673<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">float m[3][3]; 674auto & inv = inverse(m);</code></pre> 675</div> 676</div> 677<div class="paragraph"> 678<p>Above, the object returned by <a href="#mat_inverse"><code>inverse</code></a> and captured by <code>inv</code> can not be of type <code>float[3][3]</code>, 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 <a href="#deduce_mat"><code>deduce_mat</code></a> template.</p> 679</div> 680</div> 681<div class="sect3"> 682<h4 id="_converting_between_different_quaternion_vector_and_matrix_types">Converting between different quaternion, vector and matrix types</h4> 683<div class="paragraph"> 684<p>Any time you need to create a matrix of a particular C++ type from any other compatible matrix type, you can use the <a href="#convert_to"><code>convert_to</code></a> function:</p> 685</div> 686<div class="listingblock"> 687<div class="content"> 688<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">user_matrix2 m=convert_to<user_matrix2>(m1 * m2);</code></pre> 689</div> 690</div> 691</div> 692</div> 693</div> 694</div> 695<div class="sect1"> 696<h2 id="reference">Reference</h2> 697<div class="sectionbody"> 698<div class="sect2"> 699<h3 id="_header_files">Header Files</h3> 700<div class="paragraph"> 701<p>QVM is split into multiple headers to allow different compilation units to <code>#include</code> only the components they need. Each function in this document specifies the exact header that must be <code>#included</code> in order to use it.</p> 702</div> 703<div class="paragraph"> 704<p>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. <code>vec_operations2.hpp</code> contains only functions for working with 2D vectors.</p> 705</div> 706<div class="paragraph"> 707<p>The header <code>boost/qvm/all.hpp</code> is provided for convenience. It includes all other QVM headers.</p> 708</div> 709<table class="tableblock frame-all grid-all stretch"> 710<caption class="title">Table 1. Quaternion header files</caption> 711<colgroup> 712<col style="width: 33.3333%;"> 713<col style="width: 66.6667%;"> 714</colgroup> 715<tbody> 716<tr> 717<td class="tableblock halign-left valign-top"><p class="tableblock">Quaternion traits</p></td> 718<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/quat_traits.hpp> 719#include <boost/qvm/quat_traits_array.hpp> 720#include <boost/qvm/deduce_quat.hpp></pre></div></td> 721</tr> 722<tr> 723<td class="tableblock halign-left valign-top"><p class="tableblock">Quaternion element access</p></td> 724<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/quat_access.hpp></pre></div></td> 725</tr> 726<tr> 727<td class="tableblock halign-left valign-top"><p class="tableblock">Quaternion operations</p></td> 728<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/quat_operations.hpp></pre></div></td> 729</tr> 730<tr> 731<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#quat"><code>quat</code></a> class template</p></td> 732<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/quat.hpp></pre></div></td> 733</tr> 734</tbody> 735</table> 736<table class="tableblock frame-all grid-all stretch"> 737<caption class="title">Table 2. Vector header files</caption> 738<colgroup> 739<col style="width: 33.3333%;"> 740<col style="width: 66.6667%;"> 741</colgroup> 742<tbody> 743<tr> 744<td class="tableblock halign-left valign-top"><p class="tableblock">Vector traits</p></td> 745<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/vec_traits.hpp> 746#include <boost/qvm/vec_traits_array.hpp> 747#include <boost/qvm/deduce_vec.hpp></pre></div></td> 748</tr> 749<tr> 750<td class="tableblock halign-left valign-top"><p class="tableblock">Vector element access</p></td> 751<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/vec_access.hpp></pre></div></td> 752</tr> 753<tr> 754<td class="tableblock halign-left valign-top"><p class="tableblock">Vector <a href="#swizzling">swizzling</a></p></td> 755<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/swizzle.hpp> 756#include <boost/qvm/swizzle2.hpp> 757#include <boost/qvm/swizzle3.hpp> 758#include <boost/qvm/swizzle4.hpp></pre></div></td> 759</tr> 760<tr> 761<td class="tableblock halign-left valign-top"><p class="tableblock">Vector operations</p></td> 762<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/vec_operations.hpp> 763#include <boost/qvm/vec_operations2.hpp> 764#include <boost/qvm/vec_operations3.hpp> 765#include <boost/qvm/vec_operations4.hpp></pre></div></td> 766</tr> 767<tr> 768<td class="tableblock halign-left valign-top"><p class="tableblock">Quaternion-vector operations</p></td> 769<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/quat_vec_operations.hpp></pre></div></td> 770</tr> 771<tr> 772<td class="tableblock halign-left valign-top"><p class="tableblock">Vector-matrix operations</p></td> 773<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/vec_mat_operations.hpp></pre></div></td> 774</tr> 775<tr> 776<td class="tableblock halign-left valign-top"><p class="tableblock">Vector-matrix <a href="#view_proxy">view proxies</a></p></td> 777<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/map_vec_mat.hpp></pre></div></td> 778</tr> 779<tr> 780<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#vec"><code>vec</code></a> class template</p></td> 781<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/vec.hpp></pre></div></td> 782</tr> 783</tbody> 784</table> 785<table class="tableblock frame-all grid-all stretch"> 786<caption class="title">Table 3. Matrix header files</caption> 787<colgroup> 788<col style="width: 33.3333%;"> 789<col style="width: 66.6667%;"> 790</colgroup> 791<tbody> 792<tr> 793<td class="tableblock halign-left valign-top"><p class="tableblock">Matrix traits</p></td> 794<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/mat_traits.hpp> 795#include <boost/qvm/mat_traits_array.hpp> 796#include <boost/qvm/deduce_mat.hpp></pre></div></td> 797</tr> 798<tr> 799<td class="tableblock halign-left valign-top"><p class="tableblock">Matrix element access</p></td> 800<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/mat_access.hpp></pre></div></td> 801</tr> 802<tr> 803<td class="tableblock halign-left valign-top"><p class="tableblock">Matrix operations</p></td> 804<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/mat_operations.hpp> 805#include <boost/qvm/mat_operations2.hpp> 806#include <boost/qvm/mat_operations3.hpp> 807#include <boost/qvm/mat_operations4.hpp></pre></div></td> 808</tr> 809<tr> 810<td class="tableblock halign-left valign-top"><p class="tableblock">Matrix-matrix <a href="#view_proxy">view proxies</a></p></td> 811<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/map_mat_mat.hpp></pre></div></td> 812</tr> 813<tr> 814<td class="tableblock halign-left valign-top"><p class="tableblock">Matrix-vector <a href="#view_proxy">view proxies</a></p></td> 815<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/map_mat_vec.hpp></pre></div></td> 816</tr> 817<tr> 818<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#mat"><code>mat</code></a> class template</p></td> 819<td class="tableblock halign-left valign-top"><div class="literal"><pre>#include <boost/qvm/mat.hpp></pre></div></td> 820</tr> 821</tbody> 822</table> 823</div> 824<div class="sect2"> 825<h3 id="type_traits">Type Traits System</h3> 826<div class="paragraph"> 827<p>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.</p> 828</div> 829<hr> 830<div class="sect3"> 831<h4 id="scalar_requirements">Scalar Requirements</h4> 832<div class="paragraph"> 833<p>A valid scalar type <code>S</code> must have accessible destructor, default constructor, copy constructor and assignment operator, and must support the following operations:</p> 834</div> 835<div class="listingblock"> 836<div class="content"> 837<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">S operator*( S, S ); 838S operator/( S, S ); 839S operator+( S, S ); 840S operator-( S, S ); 841 842S & operator*=( S &, S ); 843S & operator/=( S &, S ); 844S & operator+=( S &, S ); 845S & operator-=( S &, S ); 846 847bool operator==( S, S ); 848bool operator!=( S, S );</code></pre> 849</div> 850</div> 851<div class="paragraph"> 852<p>In addition, the expression <code>S(0)</code> should construct a scalar of value zero, and <code>S(1)</code> should construct a scalar of value one, or else the <a href="#scalar_traits"><code>scalar_traits</code></a> template must be specialized appropriately.</p> 853</div> 854<hr> 855</div> 856<div class="sect3"> 857<h4 id="is_scalar"><code>is_scalar</code></h4> 858<div class="listingblock"> 859<div class="title">#include <boost/qvm/scalar_traits.hpp></div> 860<div class="content"> 861<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 862 863 template <class T> 864 struct is_scalar { 865 static bool const value=false; 866 }; 867 868 template <> struct is_scalar<char> { static bool const value=true; }; 869 template <> struct is_scalar<signed char> { static bool const value=true; }; 870 template <> struct is_scalar<unsigned char> { static bool const value=true; }; 871 template <> struct is_scalar<signed short> { static bool const value=true; }; 872 template <> struct is_scalar<unsigned short> { static bool const value=true; }; 873 template <> struct is_scalar<signed int> { static bool const value=true; }; 874 template <> struct is_scalar<unsigned int> { static bool const value=true; }; 875 template <> struct is_scalar<signed long> { static bool const value=true; }; 876 template <> struct is_scalar<unsigned long> { static bool const value=true; }; 877 template <> struct is_scalar<float> { static bool const value=true; }; 878 template <> struct is_scalar<double> { static bool const value=true; }; 879 template <> struct is_scalar<long double> { static bool const value=true; }; 880 881} }</code></pre> 882</div> 883</div> 884<div class="paragraph"> 885<p>This template defines a compile-time boolean constant value which can be used to determine whether a type <code>T</code> is a valid scalar type. It must be specialized together with the <a href="#scalar_traits"><code>scalar_traits</code></a> template in order to introduce a user-defined scalar type to QVM. Such types must satisfy the <a href="#scalar_requirements">scalar requirements</a>.</p> 886</div> 887<hr> 888</div> 889<div class="sect3"> 890<h4 id="scalar_traits"><code>scalar_traits</code></h4> 891<div class="listingblock"> 892<div class="title">#include <boost/qvm/scalar_traits.hpp></div> 893<div class="content"> 894<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 895 896 template <class Scalar> 897 struct scalar_traits { 898 899 BOOST_QVM_INLINE_CRITICAL 900 static Scalar value( int v ) { 901 return Scalar(v); 902 } 903 904 }; 905 906} }</code></pre> 907</div> 908</div> 909<div class="paragraph"> 910<p>This template may be specialized for user-defined scalar types to define the appropriate conversion from <code>int</code>; this is primarily used whenever QVM needs to deduce a zero or one value.</p> 911</div> 912<hr> 913</div> 914<div class="sect3"> 915<h4 id="deduce_scalar"><code>deduce_scalar</code></h4> 916<div class="listingblock"> 917<div class="title">#include <boost/qvm/deduce_scalar.hpp></div> 918<div class="content"> 919<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 920 921 template <class A,class B> 922 struct deduce_scalar 923 { 924 typedef typename impl<A,B>::type type; 925 }; 926 927} }</code></pre> 928</div> 929</div> 930<div class="dlist"> 931<dl> 932<dt class="hdlist1">Requires: </dt> 933<dd> 934<p><code>A</code> and <code>B</code> satisfy the <a href="#scalar_requirements">scalar requirements</a>.</p> 935</dd> 936<dt class="hdlist1">Returns: </dt> 937<dd> 938<p>If <code>A</code> and <code>B</code> are the same type, <code>impl<A,B>::type</code> returns that type. Otherwise, <code>impl<A,B>::type</code> is well defined for the following types only: <code>signed</code>/<code>unsigned char</code>, <code>signed</code>/<code>unsigned short</code>, <code>signed</code>/<code>unsigned int</code>, <code>signed</code>/<code>unsigned long</code>, <code>float</code> and <code>double</code>. The deduction logic is as follows:</p> 939<div class="ulist"> 940<ul> 941<li> 942<p>if either of <code>A</code> and <code>B</code> is <code>double</code>, the result is <code>double</code>;</p> 943</li> 944<li> 945<p>else, if one of <code>A</code> or <code>B</code> is an integer type and the other is <code>float</code>, the result is <code>float</code>;</p> 946</li> 947<li> 948<p>else, if one of <code>A</code> or <code>B</code> 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.</p> 949</li> 950</ul> 951</div> 952</dd> 953</dl> 954</div> 955<div class="admonitionblock note"> 956<table> 957<tr> 958<td class="icon"> 959<i class="fa icon-note" title="Note"></i> 960</td> 961<td class="content"> 962This 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. 963</td> 964</tr> 965</table> 966</div> 967<hr> 968</div> 969<div class="sect3"> 970<h4 id="scalar"><code>scalar</code></h4> 971<div class="listingblock"> 972<div class="title">#include <boost/qvm/scalar_traits.hpp></div> 973<div class="content"> 974<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 975 976 template <class T> 977 struct scalar { 978 typedef /*exact definition unspecified*/ type; 979 }; 980 981} }</code></pre> 982</div> 983</div> 984<div class="paragraph"> 985<p>The expression <a href="#quat_traits"><code>quat_traits<T>::scalar_type</code></a> evaluates to the scalar type of the quaternion type <code>T</code> (if <a href="#is_quat"><code>is_quat<T>::value</code></a> is <code>true</code>).</p> 986</div> 987<div class="paragraph"> 988<p>The expression <a href="#vec_traits"><code>vec_traits<T>::scalar_type</code></a> evaluates to the scalar type of the vector type <code>T</code> (if <a href="#is_vec"><code>is_vec<T>::value</code></a> is <code>true</code>).</p> 989</div> 990<div class="paragraph"> 991<p>The expression <a href="#mat_traits"><code>mat_traits<T>::scalar_type</code></a> evaluates to the scalar type of the matrix type <code>T</code> (if <a href="#is_mat"><code>is_mat<T>::value</code></a> is <code>true</code>).</p> 992</div> 993<div class="paragraph"> 994<p>The expression <code>scalar<T>::type</code> is similar, except that it automatically detects whether <code>T</code> is a vector or a matrix or a quaternion type.</p> 995</div> 996<hr> 997</div> 998<div class="sect3"> 999<h4 id="is_quat"><code>is_quat</code></h4> 1000<div class="listingblock"> 1001<div class="title">#include <boost/qvm/quat_traits.hpp></div> 1002<div class="content"> 1003<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1004 1005 template <class T> 1006 struct is_quat { 1007 1008 static bool const value = false; 1009 1010 }; 1011 1012} }</code></pre> 1013</div> 1014</div> 1015<div class="paragraph"> 1016<p>This type template defines a compile-time boolean constant value which can be used to determine whether a type <code>T</code> is a quaternion type. For quaternion types, the <a href="#quat_traits"><code>quat_traits</code></a> template can be used to access their elements generically, or to obtain their <code>scalar type</code>.</p> 1017</div> 1018<hr> 1019</div> 1020<div class="sect3"> 1021<h4 id="quat_traits"><code>quat_traits</code></h4> 1022<div class="listingblock"> 1023<div class="title">#include <boost/qvm/quat_traits.hpp></div> 1024<div class="content"> 1025<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1026 1027 template <class Q> 1028 struct quat_traits { 1029 1030 /*main template members unspecified*/ 1031 1032 }; 1033 1034 /* 1035 User-defined (possibly partial) specializations: 1036 1037 template <> 1038 struct quat_traits<Q> { 1039 1040 typedef <<user-defined>> scalar_type; 1041 1042 template <int I> 1043 static inline scalar_type read_element( Quaternion const & q ); 1044 1045 template <int I> 1046 static inline scalar_type & write_element( Quaternion & q ); 1047 1048 }; 1049 */ 1050 1051} }</code></pre> 1052</div> 1053</div> 1054<div class="paragraph"> 1055<p>The <code>quat_traits</code> template must be specialized for (user-defined) quaternion types in order to enable quaternion operations defined in QVM headers for objects of those types.</p> 1056</div> 1057<div class="admonitionblock note"> 1058<table> 1059<tr> 1060<td class="icon"> 1061<i class="fa icon-note" title="Note"></i> 1062</td> 1063<td class="content"> 1064QVM quaternion operations do not require that quaternion types are copyable. 1065</td> 1066</tr> 1067</table> 1068</div> 1069<div class="paragraph"> 1070<p>The main <code>quat_traits</code> template members are not specified. Valid specializations are required to define the following members:</p> 1071</div> 1072<div class="ulist"> 1073<ul> 1074<li> 1075<p><code>scalar_type</code>: the expression <code>quat_traits<Quaternion>::scalar_type</code> must be a value type which satisfies the <a href="#scalar_requirements"><code>scalar requirements</code></a>.</p> 1076</li> 1077</ul> 1078</div> 1079<div class="paragraph"> 1080<p>In addition, valid specializations of the <code>quat_traits</code> template must define at least one of the following access functions as static members, where <code>q</code> is an object of type <code>Quaternion</code>, and <code>I</code> is compile-time integer constant:</p> 1081</div> 1082<div class="ulist"> 1083<ul> 1084<li> 1085<p><code>read_element</code>: the expression <code>quat_traits<Quaternion>::read_element<I>(q)</code> returns either a copy of or a <code>const</code> reference to the <code>I</code>-th element of <code>q</code>.</p> 1086</li> 1087<li> 1088<p><code>write_element</code>: the expression <code>quat_traits<Quaternion>::write_element<I>(q)</code> returns mutable reference to the <code>I</code>-th element of <code>q</code>.</p> 1089</li> 1090</ul> 1091</div> 1092<div class="admonitionblock note"> 1093<table> 1094<tr> 1095<td class="icon"> 1096<i class="fa icon-note" title="Note"></i> 1097</td> 1098<td class="content"> 1099For the quaternion <code>a + bi + cj + dk</code>, the elements are assumed to be in the following order: <code>a</code>, <code>b</code>, <code>c</code>, <code>d</code>; that is, <code>I</code>=<code>0</code>/<code>1</code>/<code>2</code>/<code>3</code> would access <code>a</code>/<code>b</code>/<code>c</code>/<code>d</code>. 1100</td> 1101</tr> 1102</table> 1103</div> 1104<div class="paragraph"> 1105<p>It is illegal to call any of the above functions unless <code>is_quat<Quaternion>::value</code> is true. Even then, quaternion types are allowed to define only a subset of the access functions.</p> 1106</div> 1107<div class="paragraph"> 1108<p>Below is an example of a user-defined quaternion type, and its corresponding specialization of the quat_traits template:</p> 1109</div> 1110<div class="listingblock"> 1111<div class="content"> 1112<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">#include <boost/qvm/quat_traits.hpp> 1113 1114struct fquat { float a[4]; }; 1115 1116namespace boost { namespace qvm { 1117 1118 template <> 1119 struct quat_traits<fquat> { 1120 1121 typedef float scalar_type; 1122 1123 template <int I> 1124 static inline scalar_type & write_element( fquat & q ) { 1125 return q.a[I]; 1126 } 1127 1128 template <int I> 1129 static inline scalar_type read_element( fquat const & q ) { 1130 return q.a[I]; 1131 } 1132 1133 }; 1134 1135} }</code></pre> 1136</div> 1137</div> 1138<div class="paragraph"> 1139<p>Equivalently, using the <a href="#quat_traits_defaults"><code>quat_traits_defaults</code></a> template the above can be shortened to:</p> 1140</div> 1141<div class="listingblock"> 1142<div class="content"> 1143<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1144 1145 template <> 1146 struct quat_traits<fquat>: quat_traits_defaults<fquat,float> { 1147 1148 template <int I> 1149 static inline scalar_type & write_element( fquat & q ) { 1150 return q.a[I]; 1151 } 1152 1153 }; 1154 1155} }</code></pre> 1156</div> 1157</div> 1158<hr> 1159</div> 1160<div class="sect3"> 1161<h4 id="quat_traits_defaults"><code>quat_traits_defaults</code></h4> 1162<div class="listingblock"> 1163<div class="title">#include <boost/qvm/quat_traits_defaults.hpp></div> 1164<div class="content"> 1165<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1166 1167 template <class QuatType,class ScalarType> 1168 struct quat_traits_defaults { 1169 1170 typedef QuatType quat_type; 1171 1172 typedef ScalarType scalar_type; 1173 1174 template <int I> 1175 static BOOST_QVM_INLINE_CRITICAL 1176 scalar_type read_element( quat_type const & x ) { 1177 return quat_traits<quat_type>::template 1178 write_element<I>(const_cast<quat_type &>(x)); 1179 } 1180 1181 }; 1182 1183} }</code></pre> 1184</div> 1185</div> 1186<div class="paragraph"> 1187<p>The <code>quat_traits_defaults</code> template is designed to be used as a public base for user-defined specializations of the <a href="#quat_traits"><code>quat_traits</code></a> template, to easily define the required members. If it is used, the only member that must be defined by the user in a <code>quat_traits</code> specialization is <code>write_element</code>; the <code>quat_traits_defaults</code> base will define <code>read_element</code>, as well as <code>scalar_type</code> automatically.</p> 1188</div> 1189<hr> 1190</div> 1191<div class="sect3"> 1192<h4 id="deduce_quat"><code>deduce_quat</code></h4> 1193<div class="listingblock"> 1194<div class="title">#include <boost/qvm/deduce_quat.hpp></div> 1195<div class="content"> 1196<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1197 1198 template <class Q> 1199 struct deduce_quat { 1200 typedef Q type; 1201 }; 1202 1203} }</code></pre> 1204</div> 1205</div> 1206<div class="dlist"> 1207<dl> 1208<dt class="hdlist1">Requires: </dt> 1209<dd> 1210<div class="ulist"> 1211<ul> 1212<li> 1213<p><code><a href="#is_quat">is_quat</a><Q>::value</code> is <code>true</code>;</p> 1214</li> 1215<li> 1216<p><code><a href="#is_quat">is_quat</a><deduce_quat<Q>::type>::value</code> must be <code>true</code>;</p> 1217</li> 1218<li> 1219<p><code>deduce_quat<Q>::type</code> must be copyable.</p> 1220</li> 1221</ul> 1222</div> 1223</dd> 1224</dl> 1225</div> 1226<div class="paragraph"> 1227<p>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 <code>Q</code> itself may be non-copyable.</p> 1228</div> 1229<div class="paragraph"> 1230<p>The main template definition returns <code>Q</code>, 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.</p> 1231</div> 1232<div class="paragraph"> 1233<p>A typical use of the <code>deduce_quat</code> 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.</p> 1234</div> 1235<hr> 1236</div> 1237<div class="sect3"> 1238<h4 id="deduce_quat2"><code>deduce_quat2</code></h4> 1239<div class="listingblock"> 1240<div class="title">#include <boost/qvm/deduce_quat.hpp></div> 1241<div class="content"> 1242<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1243 1244 template <class A,class B> 1245 struct deduce_quat2 { 1246 typedef /*unspecified*/ type; 1247 }; 1248 1249} }</code></pre> 1250</div> 1251</div> 1252<div class="dlist"> 1253<dl> 1254<dt class="hdlist1">Requires: </dt> 1255<dd> 1256<div class="ulist"> 1257<ul> 1258<li> 1259<p>Both <code><a href="#scalar">scalar</a><A>::type</code> and <code>scalar<B>::type</code> are well defined;</p> 1260</li> 1261<li> 1262<p><code><a href="#is_quat">is_quat</a><A>::value</code> || <code>is_quat<B>::value</code> is <code>true</code>;</p> 1263</li> 1264<li> 1265<p><code>is_quat<deduce_quat2<A,B>::type>::value</code> must be <code>true</code>;</p> 1266</li> 1267<li> 1268<p><code>deduce_quat2<A,B>::type</code> must be copyable.</p> 1269</li> 1270</ul> 1271</div> 1272</dd> 1273</dl> 1274</div> 1275<div class="paragraph"> 1276<p>This template is used by QVM whenever it needs to deduce a quaternion type from the types of two user-supplied function parameters. The returned type must have accessible copy constructor (the <code>A</code> and <code>B</code> types themselves could be non-copyable, and either one of them may not be a quaternion type.)</p> 1277</div> 1278<div class="paragraph"> 1279<p>The main template definition returns an unspecified quaternion type with <a href="#quat_traits"><code>scalar_type</code></a> obtained by <code><a href="#deduce_scalar">deduce_scalar</a><A,B>::type</code>, except if <code>A</code> and <code>B</code> are the same quaternion type <code>Q</code>, in which case <code>Q</code> 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.</p> 1280</div> 1281<div class="paragraph"> 1282<p>A typical use of the <code>deduce_quat2</code> 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.</p> 1283</div> 1284<hr> 1285</div> 1286<div class="sect3"> 1287<h4 id="is_vec"><code>is_vec</code></h4> 1288<div class="listingblock"> 1289<div class="title">#include <boost/qvm/vec_traits.hpp></div> 1290<div class="content"> 1291<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1292 1293 template <class T> 1294 struct is_vec { 1295 1296 static bool const value = false; 1297 1298 }; 1299 1300 } }</code></pre> 1301</div> 1302</div> 1303<div class="paragraph"> 1304<p>This type template defines a compile-time boolean constant value which can be used to determine whether a type <code>T</code> is a vector type. For vector types, the <a href="#vec_traits"><code>vec_traits</code></a> template can be used to access their elements generically, or to obtain their dimension and <code>scalar type</code>.</p> 1305</div> 1306<hr> 1307</div> 1308<div class="sect3"> 1309<h4 id="vec_traits"><code>vec_traits</code></h4> 1310<div class="listingblock"> 1311<div class="title">#include <boost/qvm/vec_traits.hpp></div> 1312<div class="content"> 1313<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1314 1315 template <class V> 1316 struct vec_traits { 1317 1318 /*main template members unspecified*/ 1319 1320 }; 1321 1322 /* 1323 User-defined (possibly partial) specializations: 1324 1325 template <> 1326 struct vec_traits<V> { 1327 1328 static int const dim = <<user-defined>>; 1329 1330 typedef <<user-defined>> scalar_type; 1331 1332 template <int I> 1333 static inline scalar_type read_element( Vector const & v ); 1334 1335 template <int I> 1336 static inline scalar_type & write_element( Vector & v ); 1337 1338 static inline scalar_type read_element_idx( int i, Vector const & v ); 1339 static inline scalar_type & write_element_idx( int i, Vector & v ); 1340 1341 }; 1342 */ 1343 1344} }</code></pre> 1345</div> 1346</div> 1347<div class="paragraph"> 1348<p>The <code>vec_traits</code> 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.</p> 1349</div> 1350<div class="admonitionblock note"> 1351<table> 1352<tr> 1353<td class="icon"> 1354<i class="fa icon-note" title="Note"></i> 1355</td> 1356<td class="content"> 1357QVM vector operations do not require that vector types are copyable. 1358</td> 1359</tr> 1360</table> 1361</div> 1362<div class="paragraph"> 1363<p>The main <code>vec_traits</code> template members are not specified. Valid specializations are required to define the following members:</p> 1364</div> 1365<div class="ulist"> 1366<ul> 1367<li> 1368<p><code>dim</code>: the expression <code>vec_traits<Vector>::dim</code> must evaluate to a compile-time integer constant greater than 0 that specifies the vector size.</p> 1369</li> 1370<li> 1371<p><code>scalar_type</code>: the expression <code>vec_traits<Vector>::scalar_type</code> must be a value type which satisfies the <a href="#scalar_requirements"><code>scalar requirements</code></a>.</p> 1372</li> 1373</ul> 1374</div> 1375<div class="paragraph"> 1376<p>In addition, valid specializations of the <code>vec_traits</code> template may define the following access functions as static members, where <code>v</code> is an object of type <code>Vector</code>, <code>I</code> is a compile-time integer constant, and <code>i</code> is a variable of type <code>int</code>:</p> 1377</div> 1378<div class="ulist"> 1379<ul> 1380<li> 1381<p><code>read_element</code>: the expression <code>vec_traits<Vector>::read_element<I>(v)</code> returns either a copy of or a const reference to the <code>I</code>-th element of <code>v</code>.</p> 1382</li> 1383<li> 1384<p><code>write_element</code>: the expression <code>vec_traits<Vector>::write_element<I>(v)</code> returns mutable reference to the <code>I</code>-th element of <code>v</code>.</p> 1385</li> 1386<li> 1387<p><code>read_element_idx</code>: the expression <code>vec_traits<Vector>::read_element_idx(i,v)</code> returns either a copy of or a <code>const</code> reference to the <code>i</code>-th element of <code>v</code>.</p> 1388</li> 1389<li> 1390<p><code>write_element_idx</code>: the expression <code>vec_traits<Vector>::write_element_idx(i,v)</code> returns mutable reference to the <code>i</code>-th element of <code>v</code>.</p> 1391</li> 1392</ul> 1393</div> 1394<div class="paragraph"> 1395<p>It is illegal to call any of the above functions unless <code>is_vec<Vector>::value</code> is true. Even then, vector types are allowed to define only a subset of the access functions. The general requirements are:</p> 1396</div> 1397<div class="ulist"> 1398<ul> 1399<li> 1400<p>At least one of <code>read_element</code> or <code>write_element</code> must be defined;</p> 1401</li> 1402<li> 1403<p>If <code>read_element_idx</code> is defined, <code>read_element</code> must also be defined;</p> 1404</li> 1405<li> 1406<p>If <code>write_element_idx</code> is defined, <code>write_element</code> must also be defined.</p> 1407</li> 1408</ul> 1409</div> 1410<div class="paragraph"> 1411<p>Below is an example of a user-defined 3D vector type, and its corresponding specialization of the <code>vec_traits</code> template:</p> 1412</div> 1413<div class="listingblock"> 1414<div class="content"> 1415<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">#include <boost/qvm/vec_traits.hpp> 1416 1417struct float3 { float a[3]; }; 1418 1419namespace boost { namespace qvm { 1420 1421 template <> 1422 struct vec_traits<float3> { 1423 1424 static int const dim=3; 1425 1426 typedef float scalar_type; 1427 1428 template <int I> 1429 static inline scalar_type & write_element( float3 & v ) { 1430 return v.a[I]; 1431 } 1432 1433 template <int I> 1434 static inline scalar_type read_element( float3 const & v ) { 1435 return v.a[I]; 1436 } 1437 1438 static inline scalar_type & write_element_idx( int i, float3 & v ) { 1439 return v.a[i]; 1440 } //optional 1441 1442 static inline scalar_type read_element_idx( int i, float3 const & v ) { 1443 return v.a[i]; 1444 } //optional 1445 1446 }; 1447 1448} }</code></pre> 1449</div> 1450</div> 1451<div class="paragraph"> 1452<p>Equivalently, using the <a href="#vec_traits_defaults"><code>vec_traits_defaults</code></a> template the above can be shortened to:</p> 1453</div> 1454<div class="listingblock"> 1455<div class="content"> 1456<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1457 1458 template <> 1459 struct vec_traits<float3>: vec_traits_defaults<float3,float,3> 1460 { 1461 1462 template <int I> 1463 static inline scalar_type & write_element( float3 & v ) { 1464 return v.a[I]; 1465 } 1466 1467 static inline scalar_type & write_element_idx( int i, float3 & v ) { 1468 return v.a[i]; 1469 } //optional 1470 1471 }; 1472 1473} }</code></pre> 1474</div> 1475</div> 1476<hr> 1477</div> 1478<div class="sect3"> 1479<h4 id="vec_traits_defaults"><code>vec_traits_defaults</code></h4> 1480<div class="listingblock"> 1481<div class="title">#include <boost/qvm/vec_traits_defaults.hpp></div> 1482<div class="content"> 1483<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1484 1485 template <class VecType,class ScalarType,int Dim> 1486 struct vec_traits_defaults { 1487 1488 typedef VecType vec_type; 1489 typedef ScalarType scalar_type; 1490 static int const dim=Dim; 1491 1492 template <int I> 1493 static BOOST_QVM_INLINE_CRITICAL 1494 scalar_type write_element( vec_type const & x ) { 1495 return vec_traits<vec_type>::template write_element<I>(const_cast<vec_type &>(x)); 1496 } 1497 1498 static BOOST_QVM_INLINE_CRITICAL 1499 scalar_type read_element_idx( int i, vec_type const & x ) { 1500 return vec_traits<vec_type>::write_element_idx(i,const_cast<vec_type &>(x)); 1501 } 1502 1503 protected: 1504 1505 static BOOST_QVM_INLINE_TRIVIAL 1506 scalar_type & write_element_idx( int i, vec_type & m ) { 1507 /* unspecified */ 1508 } 1509 }; 1510 1511} }</code></pre> 1512</div> 1513</div> 1514<div class="paragraph"> 1515<p>The <code>vec_traits_defaults</code> template is designed to be used as a public base for user-defined specializations of the <a href="#vec_traits"><code>vec_traits</code></a> template, to easily define the required members. If it is used, the only member that must be defined by the user in a <code>vec_traits</code> specialization is <code>write_element</code>; the <code>vec_traits_defaults</code> base will define <code>read_element</code>, as well as <code>scalar_type</code> and <code>dim</code> automatically.</p> 1516</div> 1517<div class="paragraph"> 1518<p>Optionally, the user may also define <code>write_element_idx</code>, in which case the <code>vec_traits_defaults</code> base will provide a suitable <code>read_element_idx</code> definition automatically. If not, <code>vec_traits_defaults</code> defines a protected implementation of <code>write_element_idx</code> which may be made publicly available by the deriving <code>vec_traits</code> specialization in case the vector type for which it is being specialized can not be indexed efficiently. This <code>write_element_idx</code> function is less efficient (using meta-programming), implemented in terms of the required user-defined <code>write_element</code>.</p> 1519</div> 1520<hr> 1521</div> 1522<div class="sect3"> 1523<h4 id="deduce_vec"><code>deduce_vec</code></h4> 1524<div class="listingblock"> 1525<div class="title">#include <boost/qvm/deduce_vec.hpp></div> 1526<div class="content"> 1527<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1528 1529 template <class V, int Dim=vec_traits<Vector>::dim> 1530 struct deduce_vec { 1531 1532 typedef /*unspecified*/ type; 1533 1534 }; 1535 1536} }</code></pre> 1537</div> 1538</div> 1539<div class="dlist"> 1540<dl> 1541<dt class="hdlist1">Requires: </dt> 1542<dd> 1543<div class="ulist"> 1544<ul> 1545<li> 1546<p><code><a href="#is_vec">is_vec</a><V>::value</code> is <code>true</code>;</p> 1547</li> 1548<li> 1549<p><code>is_vec<deduce_vec<V>::type>::value</code> must be <code>true</code>;</p> 1550</li> 1551<li> 1552<p><code>deduce_vec<V>::type</code> must be copyable;</p> 1553</li> 1554<li> 1555<p><code>vec_traits<deduce_vec<V>::type>::dim==Dim</code>.</p> 1556</li> 1557</ul> 1558</div> 1559</dd> 1560</dl> 1561</div> 1562<div class="paragraph"> 1563<p>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 <code>V</code> may be non-copyable.</p> 1564</div> 1565<div class="paragraph"> 1566<p>The main template definition returns an unspecified copyable vector type of size <code>Dim</code>, except if <code><a href="#vec_traits">vec_traits</a><V>::dim==Dim</code>, in which case it returns <code>V</code>, which is suitable only if <code>V</code> 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.</p> 1567</div> 1568<div class="paragraph"> 1569<p>A typical use of the <code>deduce_vec</code> 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.</p> 1570</div> 1571<hr> 1572</div> 1573<div class="sect3"> 1574<h4 id="deduce_vec2"><code>deduce_vec2</code></h4> 1575<div class="listingblock"> 1576<div class="title">#include <boost/qvm/deduce_vec.hpp></div> 1577<div class="content"> 1578<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1579 1580 template <class A,class B,int Dim> 1581 struct deduce_vec2 { 1582 typedef /*unspecified*/ type; 1583 }; 1584 1585} }</code></pre> 1586</div> 1587</div> 1588<div class="dlist"> 1589<dl> 1590<dt class="hdlist1">Requires: </dt> 1591<dd> 1592<div class="ulist"> 1593<ul> 1594<li> 1595<p>Both <code><a href="#scalar">scalar</a><A>::type</code> and <code>scalar<B>::type</code> are well defined;</p> 1596</li> 1597<li> 1598<p><code><a href="#is_vec">is_vec</a><A>::value || is_vec<B>::value</code> is <code>true</code>;</p> 1599</li> 1600<li> 1601<p><code>is_vec<deduce_vec2<A,B>::type>::value</code> must be <code>true</code>;</p> 1602</li> 1603<li> 1604<p><code>deduce_vec2<A,B>::type</code> must be copyable;</p> 1605</li> 1606<li> 1607<p><code>vec_traits<deduce_vec2<A,B>::type>::dim==Dim</code>.</p> 1608</li> 1609</ul> 1610</div> 1611</dd> 1612</dl> 1613</div> 1614<div class="paragraph"> 1615<p>This template is used by QVM whenever it needs to deduce a vector type of certain dimension from the types of two user-supplied function parameters. The returned type must have accessible copy constructor (the <code>A</code> and <code>B</code> types themselves could be non-copyable, and either one of them may not be a vector type.)</p> 1616</div> 1617<div class="paragraph"> 1618<p>The main template definition returns an unspecified vector type of the requested dimension with <a href="#vec_traits"><code>scalar_type</code></a> obtained by <code><a href="#deduce_scalar">deduce_scalar</a><A,B>::type</code>, except if <code>A</code> and <code>B</code> are the same vector type <code>V</code> of dimension <code>Dim</code>, in which case <code>V</code> 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.</p> 1619</div> 1620<div class="paragraph"> 1621<p>A typical use of the <code>deduce_vec2</code> 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.</p> 1622</div> 1623<hr> 1624</div> 1625<div class="sect3"> 1626<h4 id="is_mat"><code>is_mat</code></h4> 1627<div class="listingblock"> 1628<div class="title">#include <boost/qvm/mat_traits.hpp></div> 1629<div class="content"> 1630<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1631 1632 template <class T> 1633 struct is_mat { 1634 1635 static bool const value = false; 1636 1637 }; 1638 1639} }</code></pre> 1640</div> 1641</div> 1642<div class="paragraph"> 1643<p>This type template defines a compile-time boolean constant value which can be used to determine whether a type <code>T</code> is a matrix type. For matrix types, the <a href="#mat_traits"><code>mat_traits</code></a> template can be used to access their elements generically, or to obtain their dimensions and scalar type.</p> 1644</div> 1645<hr> 1646</div> 1647<div class="sect3"> 1648<h4 id="mat_traits"><code>mat_traits</code></h4> 1649<div class="listingblock"> 1650<div class="title">#include <boost/qvm/mat_traits.hpp></div> 1651<div class="content"> 1652<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1653 1654 template <class M> 1655 struct mat_traits { 1656 1657 /*main template members unspecified*/ 1658 1659 }; 1660 1661 /* 1662 User-defined (possibly partial) specializations: 1663 1664 template <> 1665 struct mat_traits<M> { 1666 1667 static int const rows = <<user-defined>>; 1668 static int const cols = <<user-defined>>; 1669 typedef <<user-defined>> scalar_type; 1670 1671 template <int R,int C> 1672 static inline scalar_type read_element( Matrix const & m ); 1673 1674 template <int R,int C> 1675 static inline scalar_type & write_element( Matrix & m ); 1676 1677 static inline scalar_typeread_element_idx( int r, int c, Matrix const & m ); 1678 static inline scalar_type & write_element_idx( int r, int c, Matrix & m ); 1679 1680 }; 1681 */ 1682 1683} }</code></pre> 1684</div> 1685</div> 1686<div class="paragraph"> 1687<p>The <code>mat_traits</code> 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.</p> 1688</div> 1689<div class="admonitionblock note"> 1690<table> 1691<tr> 1692<td class="icon"> 1693<i class="fa icon-note" title="Note"></i> 1694</td> 1695<td class="content"> 1696The matrix operations defined by QVM do not require matrix types to be copyable. 1697</td> 1698</tr> 1699</table> 1700</div> 1701<div class="paragraph"> 1702<p>The main <code>mat_traits</code> template members are not specified. Valid specializations are required to define the following members:</p> 1703</div> 1704<div class="ulist"> 1705<ul> 1706<li> 1707<p><code>rows</code>: the expression <code>mat_traits<Matrix>::rows</code> must evaluate to a compile-time integer constant greater than 0 that specifies the number of rows in a matrix.</p> 1708</li> 1709<li> 1710<p><code>cols</code> must evaluate to a compile-time integer constant greater than 0 that specifies the number of columns in a matrix.</p> 1711</li> 1712<li> 1713<p><code>scalar_type</code>: the expression <code>mat_traits<Matrix>::scalar_type</code> must be a value type which satisfies the scalar requirements.</p> 1714</li> 1715</ul> 1716</div> 1717<div class="paragraph"> 1718<p>In addition, valid specializations of the <code>mat_traits</code> template may define the following access functions as static members, where <code>m</code> is an object of type <code>Matrix</code>, <code>R</code> and <code>C</code> are compile-time integer constants, and <code>r</code> and <code>c</code> are variables of type <code>int</code>:</p> 1719</div> 1720<div class="ulist"> 1721<ul> 1722<li> 1723<p><code>read_element</code>: the expression <code>mat_traits<Matrix>::read_element<R,C>(m)</code> returns either a copy of or a const reference to the element at row <code>R</code> and column <code>C</code> of <code>m</code>.</p> 1724</li> 1725<li> 1726<p><code>write_element</code>: the expression <code>mat_traits<Matrix>::write_element<R,C>(m)</code> returns mutable reference to the element at row <code>R</code> and column <code>C</code> of <code>m</code>.</p> 1727</li> 1728<li> 1729<p><code>read_element_idx</code>: the expression <code>mat_traits<Matrix>::read_element_idx(r,c,m)</code> returns either a copy of or a const reference to the element at row <code>r</code> and column <code>c</code> of <code>m</code>.</p> 1730</li> 1731<li> 1732<p><code>write_element_idx</code>: the expression <code>mat_traits<Matrix>::write_element_idx(r,c,m)</code> returns mutable reference to the element at row <code>r</code> and column <code>c</code> of <code>m</code>.</p> 1733</li> 1734</ul> 1735</div> 1736<div class="paragraph"> 1737<p>It is illegal to call any of the above functions unless <code>is_mat<Matrix>::value</code> is true. Even then, matrix types are allowed to define only a subset of the access functions. The general requirements are:</p> 1738</div> 1739<div class="ulist"> 1740<ul> 1741<li> 1742<p>At least one of <code>read_element</code> or <code>write_element</code> must be defined;</p> 1743</li> 1744<li> 1745<p>If <code>read_element_idx</code> is defined, <code>read_element</code> must also be defined;</p> 1746</li> 1747<li> 1748<p>If <code>write_element_idx</code> is defined, <code>write_element</code> must also be defined.</p> 1749</li> 1750</ul> 1751</div> 1752<div class="paragraph"> 1753<p>Below is an example of a user-defined 3x3 matrix type, and its corresponding specialization of the <code>mat_traits</code> template:</p> 1754</div> 1755<div class="listingblock"> 1756<div class="content"> 1757<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">#include <boost/qvm/mat_traits.hpp> 1758 1759struct float33 { float a[3][3]; }; 1760 1761namespace boost { namespace qvm { 1762 1763 template <> 1764 struct mat_traits<float33> { 1765 1766 static int const rows=3; 1767 static int const cols=3; 1768 typedef float scalar_type; 1769 1770 template <int R,int C> 1771 static inline scalar_type & write_element( float33 & m ) { 1772 return m.a[R][C]; 1773 } 1774 1775 template <int R,int C> 1776 static inline scalar_type read_element( float33 const & m ) { 1777 return m.a[R][C]; 1778 } 1779 1780 static inline scalar_type & write_element_idx( int r, int c, float33 & m ) { 1781 return m.a[r][c]; 1782 } 1783 1784 static inline scalar_type read_element_idx( int r, int c, float33 const & m ) { 1785 return m.a[r][c]; 1786 } 1787 1788 }; 1789 1790} }</code></pre> 1791</div> 1792</div> 1793<div class="paragraph"> 1794<p>Equivalently, we could use the <<mat_traits_defaults,<code>mat_traits_defaults</code> template to shorten the above to:</p> 1795</div> 1796<div class="listingblock"> 1797<div class="content"> 1798<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1799 1800 template <> 1801 struct mat_traits<float33>: mat_traits_defaults<float33,float,3,3> { 1802 1803 template <int R,int C> static inline scalar_type & write_element( float33 & m ) { return m.a[R][C]; } 1804 1805 static inline scalar_type & write_element_idx( int r, int c, float33 & m ) { 1806 return m.a[r][c]; 1807 } 1808 1809 }; 1810 1811} }</code></pre> 1812</div> 1813</div> 1814<hr> 1815</div> 1816<div class="sect3"> 1817<h4 id="mat_traits_defaults"><code>mat_traits_defaults</code></h4> 1818<div class="listingblock"> 1819<div class="title">#include <boost/qvm/mat_traits_defaults.hpp></div> 1820<div class="content"> 1821<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1822 1823 template <class MatType,class ScalarType,int Rows,int Cols> 1824 struct mat_traits_defaults 1825 { 1826 typedef MatType mat_type; 1827 typedef ScalarType scalar_type; 1828 static int const rows=Rows; 1829 static int const cols=Cols; 1830 1831 template <int Row,int Col> 1832 static BOOST_QVM_INLINE_CRITICAL 1833 scalar_type write_element( mat_type const & x ) { 1834 return mat_traits<mat_type>::template write_element<Row,Col>(const_cast<mat_type &>(x)); 1835 } 1836 1837 static BOOST_QVM_INLINE_CRITICAL 1838 scalar_type read_element_idx( int r, int c, mat_type const & x ) { 1839 return mat_traits<mat_type>::write_element_idx(r,c,const_cast<mat_type &>(x)); 1840 } 1841 1842 protected: 1843 1844 static BOOST_QVM_INLINE_TRIVIAL 1845 scalar_type & write_element_idx( int r, int c, mat_type & m ) { 1846 /* unspecified */ 1847 } 1848 }; 1849 1850} }</code></pre> 1851</div> 1852</div> 1853<div class="paragraph"> 1854<p>The <code>mat_traits_defaults</code> template is designed to be used as a public base for user-defined specializations of the <a href="#mat_traits"><code>mat_traits</code></a> template, to easily define the required members. If it is used, the only member that must be defined by the user in a <code>mat_traits</code> specialization is <code>write_element</code>; the <code>mat_traits_defaults</code> base will define <code>read_element</code>, as well as <code>scalar_type</code>, <code>rows</code> and <code>cols</code> automatically.</p> 1855</div> 1856<div class="paragraph"> 1857<p>Optionally, the user may also define <code>write_element_idx</code>, in which case the <code>mat_traits_defaults</code> base will provide a suitable <code>read_element_idx</code> definition automatically. Otherwise, <code>mat_traits_defaults</code> defines a protected implementation of <code>write_element_idx</code> which may be made publicly available by the deriving <code>mat_traits</code> specialization in case the matrix type for which it is being specialized can not be indexed efficiently. This <code>write_element_idx</code> function is less efficient (using meta-programming), implemented in terms of the required user-defined <code>write_element</code>.</p> 1858</div> 1859<hr> 1860</div> 1861<div class="sect3"> 1862<h4 id="deduce_mat"><code>deduce_mat</code></h4> 1863<div class="listingblock"> 1864<div class="title">#include <boost/qvm/deduce_mat.hpp></div> 1865<div class="content"> 1866<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1867 1868 template < 1869 class M, 1870 int Rows=mat_traits<Matrix>::rows, 1871 int Cols=mat_traits<Matrix>::cols> 1872 struct deduce_mat { 1873 1874 typedef /*unspecified*/ type; 1875 1876 }; 1877 1878} }</code></pre> 1879</div> 1880</div> 1881<div class="dlist"> 1882<dl> 1883<dt class="hdlist1">Requires: </dt> 1884<dd> 1885<div class="ulist"> 1886<ul> 1887<li> 1888<p><code><a href="#is_mat">is_mat</a><M>::value</code> is <code>true</code>;</p> 1889</li> 1890<li> 1891<p><code>is_mat<deduce_mat<M>::type>::value</code> must be <code>true</code>;</p> 1892</li> 1893<li> 1894<p><code>deduce_mat<M>::type</code> must be copyable;</p> 1895</li> 1896<li> 1897<p><code><a href="#mat_traits">mat_traits</a><deduce_mat<M>::type>::rows==Rows</code>;</p> 1898</li> 1899<li> 1900<p><code>mat_traits<deduce_mat<M>::type>::cols==Cols</code>.</p> 1901</li> 1902</ul> 1903</div> 1904</dd> 1905</dl> 1906</div> 1907<div class="paragraph"> 1908<p>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.</p> 1909</div> 1910<div class="paragraph"> 1911<p>The main template definition returns an unspecified copyable matrix type of size <code>Rows</code> x <code>Cols</code>, except if <code><a href="#mat_traits">mat_traits</a><M>::rows==Rows && mat_traits<M>::cols==Cols</code>, in which case it returns <code>M</code>, which is suitable only if <code>M</code> 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.</p> 1912</div> 1913<div class="paragraph"> 1914<p>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.</p> 1915</div> 1916<hr> 1917</div> 1918<div class="sect3"> 1919<h4 id="deduce_mat2"><code>deduce_mat2</code></h4> 1920<div class="listingblock"> 1921<div class="title">#include <boost/qvm/deduce_mat.hpp></div> 1922<div class="content"> 1923<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1924 1925 template <class A,class B,int Rows,int Cols> 1926 struct deduce_mat2 { 1927 1928 typedef /*unspecified*/ type; 1929 1930 }; 1931 1932} }</code></pre> 1933</div> 1934</div> 1935<div class="dlist"> 1936<dl> 1937<dt class="hdlist1">Requires: </dt> 1938<dd> 1939<div class="ulist"> 1940<ul> 1941<li> 1942<p>Both <code><a href="#scalar">scalar</a><A>::type</code> and <code>scalar<B>::type</code> are well defined;</p> 1943</li> 1944<li> 1945<p><code><a href="#is_mat">is_mat</a><A>::value || is_mat<B>::value</code> is <code>true</code>;</p> 1946</li> 1947<li> 1948<p><code>is_mat<deduce_mat2<A,B>::type>::value</code> must be <code>true</code>;</p> 1949</li> 1950<li> 1951<p><code>deduce_mat2<A,B>::type</code> must be copyable;</p> 1952</li> 1953<li> 1954<p><code><a href="#mat_traits">mat_traits</a><deduce_mat2<A,B>::type>::rows==Rows</code>;</p> 1955</li> 1956<li> 1957<p><code>mat_traits<deduce_mat2<A,B>::type>::cols==Cols</code>.</p> 1958</li> 1959</ul> 1960</div> 1961</dd> 1962</dl> 1963</div> 1964<div class="paragraph"> 1965<p>This template is used by QVM whenever it needs to deduce a matrix type of certain dimensions from the types of two user-supplied function parameters. The returned type must have accessible copy constructor (the <code>A</code> and <code>B</code> types themselves could be non-copyable, and either one of them may be a non-matrix type.)</p> 1966</div> 1967<div class="paragraph"> 1968<p>The main template definition returns an unspecified matrix type of the requested dimensions with <a href="#mat_traits"><code>scalar_type</code></a> obtained by <code><a href="#deduce_scalar">deduce_scalar</a><A,B>::type</code>, except if <code>A</code> and <code>B</code> are the same matrix type <code>M</code> of dimensions <code>Rows</code> x <code>Cols</code>, in which case <code>M</code> 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.</p> 1969</div> 1970<div class="paragraph"> 1971<p>A typical use of the <code>deduce_mat2</code> 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.</p> 1972</div> 1973<hr> 1974</div> 1975</div> 1976<div class="sect2"> 1977<h3 id="_built_in_quaternion_vector_and_matrix_types">Built-in Quaternion, Vector and Matrix Types</h3> 1978<div class="paragraph"> 1979<p>QVM defines several class templates (together with appropriate specializations of <a href="#quat_traits"><code>quat_traits</code></a>, <a href="#vec_traits"><code>vec_traits</code></a> and <a href="#mat_traits"><code>mat_traits</code></a> 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.</p> 1980</div> 1981<div class="sect3"> 1982<h4 id="quat"><code>quat</code></h4> 1983<div class="listingblock"> 1984<div class="title">#include <boost/qvm/quat.hpp></div> 1985<div class="content"> 1986<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 1987 1988 template <class T> 1989 struct quat { 1990 1991 T a[4]; 1992 1993 template <class R> 1994 operator R() const { 1995 R r; 1996 assign(r,*this); 1997 return r; 1998 } 1999 2000 }; 2001 2002 template <class Quaternion> 2003 struct quat_traits; 2004 2005 template <class T> 2006 struct quat_traits< quat<T> > { 2007 2008 typedef T scalar_type; 2009 2010 template <int I> 2011 static scalar_type read_element( quat<T> const & x ) { 2012 return x.a[I]; 2013 } 2014 2015 template <int I> 2016 static scalar_type & write_element( quat<T> & x ) { 2017 return x.a[I]; 2018 } 2019 2020 }; 2021 2022} }</code></pre> 2023</div> 2024</div> 2025<div class="paragraph"> 2026<p>This is a simple quaternion type. It converts to any other quaternion type.</p> 2027</div> 2028<div class="paragraph"> 2029<p>The partial specialization of the <a href="#quat_traits"><code>quat_traits</code></a> template makes the <code>quat</code> template compatible with the generic operations defined by QVM.</p> 2030</div> 2031<hr> 2032</div> 2033<div class="sect3"> 2034<h4 id="vec"><code>vec</code></h4> 2035<div class="listingblock"> 2036<div class="title">#include <boost/qvm/vec.hpp></div> 2037<div class="content"> 2038<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2039 2040 template <class T,int Dim> 2041 struct vec { 2042 2043 T a[Dim]; 2044 2045 template <class R> 2046 operator R() const { 2047 R r; 2048 assign(r,*this); 2049 return r; 2050 } 2051 2052 }; 2053 2054 template <class Vector> 2055 struct vec_traits; 2056 2057 template <class T,int Dim> 2058 struct vec_traits< vec<T,Dim> > { 2059 2060 typedef T scalar_type; 2061 static int const dim=Dim; 2062 2063 template <int I> 2064 static scalar_type read_element( vec<T,Dim> const & x ) { 2065 return x.a[I]; 2066 } 2067 2068 template <int I> 2069 static scalar_type & write_element( vec<T,Dim> & x ) { 2070 return x.a[I]; 2071 } 2072 2073 static scalar_type read_element_idx( int i, vec<T,Dim> const & x ) { 2074 return x.a[i]; 2075 } 2076 2077 static scalar_type & write_element_idx( int i, vec<T,Dim> & x ) { 2078 return x.a[i]; 2079 } 2080 }; 2081 2082} }</code></pre> 2083</div> 2084</div> 2085<div class="paragraph"> 2086<p>This is a simple vector type. It converts to any other vector type of compatible size.</p> 2087</div> 2088<div class="paragraph"> 2089<p>The partial specialization of the <a href="#vec_traits"><code>vec_traits</code></a> template makes the <code>vec</code> template compatible with the generic operations defined by QVM.</p> 2090</div> 2091<hr> 2092</div> 2093<div class="sect3"> 2094<h4 id="mat"><code>mat</code></h4> 2095<div class="listingblock"> 2096<div class="title">#include <boost/qvm/mat.hpp></div> 2097<div class="content"> 2098<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2099 2100 template <class T,int Rows,int Cols> 2101 struct mat { 2102 2103 T a[Rows][Cols]; 2104 2105 template <class R> 2106 operator R() const { 2107 R r; 2108 assign(r,*this); 2109 return r; 2110 } 2111 2112 }; 2113 2114 template <class Matrix> 2115 struct mat_traits; 2116 2117 template <class T,int Rows,int Cols> 2118 struct mat_traits< mat<T,Rows,Cols> > { 2119 2120 typedef T scalar_type; 2121 static int const rows=Rows; 2122 static int const cols=Cols; 2123 2124 template <int Row,int Col> 2125 static scalar_type read_element( mat<T,Rows,Cols> const & x ) { 2126 return x.a[Row][Col]; 2127 } 2128 2129 template <int Row,int Col> 2130 static scalar_type & write_element( mat<T,Rows,Cols> & x ) { 2131 return x.a[Row][Col]; 2132 } 2133 2134 static scalar_type read_element_idx( int row, int col, mat<T,Rows,Cols> const & x ) { 2135 return x.a[row][col]; 2136 } 2137 2138 static scalar_type & write_element_idx( int row, int col, mat<T,Rows,Cols> & x ) { 2139 return x.a[row][col]; 2140 } 2141 2142 }; 2143 2144} }</code></pre> 2145</div> 2146</div> 2147<div class="paragraph"> 2148<p>This is a simple matrix type. It converts to any other matrix type of compatible size.</p> 2149</div> 2150<div class="paragraph"> 2151<p>The partial specialization of the <a href="#mat_traits"><code>mat_traits</code></a> template makes the <code>mat</code> template compatible with the generic operations defined by QVM.</p> 2152</div> 2153<hr> 2154</div> 2155</div> 2156<div class="sect2"> 2157<h3 id="_element_access">Element Access</h3> 2158<div class="sect3"> 2159<h4 id="quat_access">Quaternions</h4> 2160<div class="listingblock"> 2161<div class="title">#include <boost/qvm/quat_access.hpp></div> 2162<div class="content"> 2163<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2164 2165 //Only enabled if: 2166 // is_quat<Q>::value 2167 2168 template <class Q> -unspecified-return-type- S( Q & q ); 2169 template <class Q> -unspecified-return-type- V( Q & q ); 2170 template <class Q> -unspecified-return-type- X( Q & q ); 2171 template <class Q> -unspecified-return-type- Y( Q & q ); 2172 template <class Q> -unspecified-return-type- Z( Q & q ); 2173 2174} }</code></pre> 2175</div> 2176</div> 2177<div class="paragraph"> 2178<p>An expression of the form <code>S(q)</code> can be used to access the scalar component of the quaternion <code>q</code>. For example,</p> 2179</div> 2180<div class="listingblock"> 2181<div class="content"> 2182<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">S(q) *= 42;</code></pre> 2183</div> 2184</div> 2185<div class="paragraph"> 2186<p>multiplies the scalar component of <code>q</code> by the scalar 42.</p> 2187</div> 2188<div class="paragraph"> 2189<p>An expression of the form <code>V(q)</code> can be used to access the vector component of the quaternion <code>q</code>. For example,</p> 2190</div> 2191<div class="listingblock"> 2192<div class="content"> 2193<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">V(q) *= 42</code></pre> 2194</div> 2195</div> 2196<div class="paragraph"> 2197<p>multiplies the vector component of <code>q</code> by the scalar 42.</p> 2198</div> 2199<div class="paragraph"> 2200<p>The <code>X</code>, <code>Y</code> and <code>Z</code> elements of the vector component can also be accessed directly using <code>X(q)</code>, <code>Y(q)</code> and <code>Z(q)</code>.</p> 2201</div> 2202<div class="admonitionblock tip"> 2203<table> 2204<tr> 2205<td class="icon"> 2206<i class="fa icon-tip" title="Tip"></i> 2207</td> 2208<td class="content"> 2209The return types are lvalues. 2210</td> 2211</tr> 2212</table> 2213</div> 2214</div> 2215<div class="sect3"> 2216<h4 id="vec_access">Vectors</h4> 2217<div class="listingblock"> 2218<div class="title">#include <boost/qvm/vec_access.hpp></div> 2219<div class="content"> 2220<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2221 2222 //Only enabled if: 2223 // is_vec<V>::value 2224 2225 template <int I,class V> -unspecified-return-type- A( V & v ); 2226 template <class V> -unspecified-return-type- A0( V & v ); 2227 template <class V> -unspecified-return-type- A1( V & v ); 2228 ... 2229 template <class V> -unspecified-return-type- A9( V & v ); 2230 2231 template <class V> -unspecified-return-type- X( V & v ); 2232 template <class V> -unspecified-return-type- Y( V & v ); 2233 template <class V> -unspecified-return-type- Z( V & v ); 2234 template <class V> -unspecified-return-type- W( V & v ); 2235 2236} }</code></pre> 2237</div> 2238</div> 2239<div class="paragraph"> 2240<p>An expression of the form of <code>A<I>(v)</code> can be used to access the <code>I</code>-th element a vector object <code>v</code>. For example, the expression:</p> 2241</div> 2242<div class="listingblock"> 2243<div class="content"> 2244<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A<1>(v) *= 42;</code></pre> 2245</div> 2246</div> 2247<div class="paragraph"> 2248<p>can be used to multiply the element at index 1 (indexing in QVM is always zero-based) of a vector <code>v</code> by 42.</p> 2249</div> 2250<div class="paragraph"> 2251<p>For convenience, there are also non-template overloads for <code>I</code> from 0 to 9; an alternative way to write the above expression is:</p> 2252</div> 2253<div class="listingblock"> 2254<div class="content"> 2255<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A1(v) *= 42;</code></pre> 2256</div> 2257</div> 2258<div class="paragraph"> 2259<p><code>X</code>, <code>Y</code>, <code>Z</code> and <code>W</code> act the same as <code>A0</code>/<code>A1</code>/<code>A2</code>/<code>A3</code>; yet another alternative way to write the above expression is:</p> 2260</div> 2261<div class="listingblock"> 2262<div class="content"> 2263<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">Y(v) *= 42;</code></pre> 2264</div> 2265</div> 2266<div class="admonitionblock tip"> 2267<table> 2268<tr> 2269<td class="icon"> 2270<i class="fa icon-tip" title="Tip"></i> 2271</td> 2272<td class="content"> 2273The return types are lvalues. 2274</td> 2275</tr> 2276</table> 2277</div> 2278</div> 2279<div class="sect3"> 2280<h4 id="swizzling">Vector Element Swizzling</h4> 2281<div class="listingblock"> 2282<div class="title">#include <boost/qvm/swizzle.hpp></div> 2283<div class="content"> 2284<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2285 2286 //*** Accessing vector elements by swizzling *** 2287 2288 //2D view proxies, only enabled if: 2289 // is_vec<V>::value 2290 template <class V> -unspecified-2D-vector-type- XX( V & v ); 2291 template <class V> -unspecified-2D-vector-type- XY( V & v ); 2292 template <class V> -unspecified-2D-vector-type- XZ( V & v ); 2293 template <class V> -unspecified-2D-vector-type- XW( V & v ); 2294 template <class V> -unspecified-2D-vector-type- X0( V & v ); 2295 template <class V> -unspecified-2D-vector-type- X1( V & v ); 2296 template <class V> -unspecified-2D-vector-type- YX( V & v ); 2297 template <class V> -unspecified-2D-vector-type- YY( V & v ); 2298 template <class V> -unspecified-2D-vector-type- YZ( V & v ); 2299 template <class V> -unspecified-2D-vector-type- YW( V & v ); 2300 template <class V> -unspecified-2D-vector-type- Y0( V & v ); 2301 template <class V> -unspecified-2D-vector-type- Y1( V & v ); 2302 template <class V> -unspecified-2D-vector-type- ZX( V & v ); 2303 template <class V> -unspecified-2D-vector-type- ZY( V & v ); 2304 template <class V> -unspecified-2D-vector-type- ZZ( V & v ); 2305 template <class V> -unspecified-2D-vector-type- ZW( V & v ); 2306 template <class V> -unspecified-2D-vector-type- Z0( V & v ); 2307 template <class V> -unspecified-2D-vector-type- Z1( V & v ); 2308 template <class V> -unspecified-2D-vector-type- WX( V & v ); 2309 template <class V> -unspecified-2D-vector-type- WY( V & v ); 2310 template <class V> -unspecified-2D-vector-type- WZ( V & v ); 2311 template <class V> -unspecified-2D-vector-type- WW( V & v ); 2312 template <class V> -unspecified-2D-vector-type- W0( V & v ); 2313 template <class V> -unspecified-2D-vector-type- W1( V & v ); 2314 ... 2315 //2D view proxies, only enabled if: 2316 // is_scalar<S>::value 2317 template <class S> -unspecified-2D-vector-type- X0( S & s ); 2318 template <class S> -unspecified-2D-vector-type- X1( S & s ); 2319 template <class S> -unspecified-2D-vector-type- XX( S & s ); 2320 ... 2321 -unspecified-2D-vector-type- _00(); 2322 -unspecified-2D-vector-type- _01(); 2323 -unspecified-2D-vector-type- _10(); 2324 -unspecified-2D-vector-type- _11(); 2325 2326 //3D view proxies, only enabled if: 2327 // is_vec<V>::value 2328 template <class V> -unspecified-3D-vector-type- XXX( V & v ); 2329 ... 2330 template <class V> -unspecified-3D-vector-type- XXW( V & v ); 2331 template <class V> -unspecified-3D-vector-type- XX0( V & v ); 2332 template <class V> -unspecified-3D-vector-type- XX1( V & v ); 2333 template <class V> -unspecified-3D-vector-type- XYX( V & v ); 2334 ... 2335 template <class V> -unspecified-3D-vector-type- XY1( V & v ); 2336 ... 2337 template <class V> -unspecified-3D-vector-type- WW1( V & v ); 2338 ... 2339 //3D view proxies, only enabled if: 2340 // is_scalar<S>::value 2341 template <class S> -unspecified-3D-vector-type- X00( S & s ); 2342 template <class S> -unspecified-3D-vector-type- X01( S & s ); 2343 ... 2344 template <class S> -unspecified-3D-vector-type- XXX( S & s ); 2345 template <class S> -unspecified-3D-vector-type- XX0( S & s ); 2346 ... 2347 -unspecified-3D-vector-type- _000(); 2348 -unspecified-3D-vector-type- _001(); 2349 -unspecified-3D-vector-type- _010(); 2350 ... 2351 -unspecified-3D-vector-type- _111(); 2352 2353 //4D view proxies, only enabled if: 2354 // is_vec<V>::value 2355 template <class V> -unspecified-4D-vector-type- XXXX( V & v ); 2356 ... 2357 template <class V> -unspecified-4D-vector-type- XXXW( V & v ); 2358 template <class V> -unspecified-4D-vector-type- XXX0( V & v ); 2359 template <class V> -unspecified-4D-vector-type- XXX1( V & v ); 2360 template <class V> -unspecified-4D-vector-type- XXYX( V & v ); 2361 ... 2362 template <class V> -unspecified-4D-vector-type- XXY1( V & v ); 2363 ... 2364 template <class V> -unspecified-4D-vector-type- WWW1( V & v ); 2365 ... 2366 //4D view proxies, only enabled if: 2367 // is_scalar<S>::value 2368 template <class S> -unspecified-4D-vector-type- X000( S & s ); 2369 template <class S> -unspecified-4D-vector-type- X001( S & s ); 2370 ... 2371 template <class S> -unspecified-4D-vector-type- XXXX( S & s ); 2372 template <class S> -unspecified-4D-vector-type- XX00( S & s ); 2373 ... 2374 -unspecified-4D-vector-type- _0000(); 2375 -unspecified-4D-vector-type- _0001(); 2376 -unspecified-4D-vector-type- _0010(); 2377 ... 2378 -unspecified-4D-vector-type- _1111(); 2379 2380} }</code></pre> 2381</div> 2382</div> 2383<div class="paragraph"> 2384<p>Swizzling allows zero-overhead direct access to a (possibly rearranged) subset of the elements of 2D, 3D and 4D vectors. For example, if <code>v</code> is a 4D vector, the expression <code>YX(v) is a 2D view proxy whose `X</code> element refers to the <code>Y</code> element of <code>v</code>, and whose <code>Y</code> element refers to the <code>X</code> element of <code>v</code>. Like other view proxies <code>YX</code> is an lvalue, that is, if <code>v2</code> is a 2D vector, one could write:</p> 2385</div> 2386<div class="listingblock"> 2387<div class="content"> 2388<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">YX(v) = v2;</code></pre> 2389</div> 2390</div> 2391<div class="paragraph"> 2392<p>The above will leave the <code>Z</code> and <code>W</code> elements of <code>v</code> unchanged but assign the <code>Y</code> element of <code>v2</code> to the <code>X</code> element of <code>v</code> and the <code>X</code> element of <code>v2</code> to the <code>Y</code> element of <code>v</code>.</p> 2393</div> 2394<div class="paragraph"> 2395<p>All permutations of <code>X</code>, <code>Y</code>, <code>Z</code>, <code>W</code>, <code>0</code>, <code>1</code> for 2D, 3D and 4D swizzling are available (if the first character of the swizzle identifier is <code>0</code> or <code>1</code>, it is preceded by a <code>_</code>, for example <code>_11XY</code>).</p> 2396</div> 2397<div class="paragraph"> 2398<p>It is valid to use the same vector element more than once: the expression <code>ZZZ(v)</code> is a 3D vector whose <code>X</code>, <code>Y</code> and <code>Z</code> elements all refer to the <code>Z</code> element of <code>v</code>.</p> 2399</div> 2400<div class="paragraph"> 2401<p>Finally, scalars can be "swizzled" to access them as vectors: the expression <code>_0X01(42.0f)</code> is a 4D vector with <code>X</code>=0, <code>Y</code>=42.0, <code>Z</code>=0, <code>W</code>=1.</p> 2402</div> 2403</div> 2404<div class="sect3"> 2405<h4 id="mat_access">Matrices</h4> 2406<div class="listingblock"> 2407<div class="title">#include <boost/qvm/mat_access.hpp></div> 2408<div class="content"> 2409<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2410 2411 //Only enabled if: 2412 // is_quat<Q>::value 2413 2414 template <int R,int C,class M> -unspecified-return-type- A( M & m ); 2415 2416 template <class M> -unspecified-return-type- A00( M & m ); 2417 template <class M> -unspecified-return-type- A01( M & m ); 2418 ... 2419 template <class M> -unspecified-return-type- A09( M & m ); 2420 template <class M> -unspecified-return-type- A10( M & m ); 2421 ... 2422 template <class M> -unspecified-return-type- A99( M & m ); 2423 2424} }</code></pre> 2425</div> 2426</div> 2427<div class="paragraph"> 2428<p>An expression of the form <code>A<R,C>(m)</code> can be used to access the element at row <code>R</code> and column <code>C</code> of a matrix object <code>m</code>. For example, the expression:</p> 2429</div> 2430<div class="listingblock"> 2431<div class="content"> 2432<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A<4,2>(m) *= 42;</code></pre> 2433</div> 2434</div> 2435<div class="paragraph"> 2436<p>can be used to multiply the element at row 4 and column 2 of a matrix <code>m</code> by 42.</p> 2437</div> 2438<div class="paragraph"> 2439<p>For convenience, there are also non-template overloads for <code>R</code> from <code>0</code> to <code>9</code> and <code>C</code> from <code>0</code> to <code>9</code>; an alternative way to write the above expression is:</p> 2440</div> 2441<div class="listingblock"> 2442<div class="content"> 2443<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A42(m) *= 42;</code></pre> 2444</div> 2445</div> 2446<div class="admonitionblock tip"> 2447<table> 2448<tr> 2449<td class="icon"> 2450<i class="fa icon-tip" title="Tip"></i> 2451</td> 2452<td class="content"> 2453The return types are lvalues. 2454</td> 2455</tr> 2456</table> 2457</div> 2458<hr> 2459</div> 2460</div> 2461<div class="sect2"> 2462<h3 id="_quaternion_operations">Quaternion Operations</h3> 2463<div class="sect3"> 2464<h4 id="quat_assign"><code>assign</code></h4> 2465<div class="listingblock"> 2466<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2467<div class="content"> 2468<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2469 2470 //Only enabled if: 2471 // is_quat<A>::value && is_quat<B>::value 2472 template <class A,class B> 2473 A & assign( A & a, B const & b ); 2474 2475} }</code></pre> 2476</div> 2477</div> 2478<div class="dlist"> 2479<dl> 2480<dt class="hdlist1">Effects: </dt> 2481<dd> 2482<p>Copies all elements of the quaternion <code>b</code> to the quaternion <code>a</code>.</p> 2483</dd> 2484<dt class="hdlist1">Returns: </dt> 2485<dd> 2486<p><code>a</code>.</p> 2487</dd> 2488</dl> 2489</div> 2490<hr> 2491</div> 2492<div class="sect3"> 2493<h4 id="quat_convert_to"><code>convert_to</code></h4> 2494<div class="listingblock"> 2495<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2496<div class="content"> 2497<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2498 2499 //Only enabled if: 2500 // is_quat<R>::value && is_quat<A>::value 2501 template <class R,class A> 2502 R convert_to( A const & a ); 2503 2504 //Only enabled if: 2505 // is_quat<R>::value && is_mat<A>::value && 2506 // mat_traits<A>::rows==3 && mat_traits<A>::cols==3 2507 template <class R,class A> 2508 R convert_to( A const & m ); 2509 2510} }</code></pre> 2511</div> 2512</div> 2513<div class="dlist"> 2514<dl> 2515<dt class="hdlist1">Requires: </dt> 2516<dd> 2517<p><code>R</code> must be copyable.</p> 2518</dd> 2519<dt class="hdlist1">Effects: </dt> 2520<dd> 2521<div class="ulist"> 2522<ul> 2523<li> 2524<p>The first overload is equivalent to: <code>R r; assign(r,a); return r;</code></p> 2525</li> 2526<li> 2527<p>The second overload assumes that <code>m</code> is an orthonormal rotation matrix and converts it to a quaternion that performs the same rotation.</p> 2528</li> 2529</ul> 2530</div> 2531</dd> 2532</dl> 2533</div> 2534<hr> 2535</div> 2536<div class="sect3"> 2537<h4 id="quat_minus_eq"><code>operator-=</code></h4> 2538<div class="listingblock"> 2539<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2540<div class="content"> 2541<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2542 2543 //Only enabled if: 2544 // is_quat<A>::value && is_quat<B>::value 2545 template <class A,class B> 2546 A & operator-=( A & a, B const & b ); 2547 2548} }</code></pre> 2549</div> 2550</div> 2551<div class="dlist"> 2552<dl> 2553<dt class="hdlist1">Effects: </dt> 2554<dd> 2555<p>Subtracts the elements of <code>b</code> from the corresponding elements of <code>a</code>.</p> 2556</dd> 2557<dt class="hdlist1">Returns: </dt> 2558<dd> 2559<p><code>a</code>.</p> 2560</dd> 2561</dl> 2562</div> 2563<hr> 2564</div> 2565<div class="sect3"> 2566<h4 id="quat_minus_unary"><code>operator-</code> (unary)</h4> 2567<div class="listingblock"> 2568<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2569<div class="content"> 2570<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2571 2572 //Only enabled if: is_quat<A>::value 2573 template <class A> 2574 typename deduce_quat<A>::type 2575 operator-( A const & a ); 2576 2577} }</code></pre> 2578</div> 2579</div> 2580<div class="dlist"> 2581<dl> 2582<dt class="hdlist1">Returns: </dt> 2583<dd> 2584<p>A quaternion of the negated elements of <code>a</code>.</p> 2585</dd> 2586</dl> 2587</div> 2588<div class="admonitionblock note"> 2589<table> 2590<tr> 2591<td class="icon"> 2592<i class="fa icon-note" title="Note"></i> 2593</td> 2594<td class="content"> 2595The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 2596</td> 2597</tr> 2598</table> 2599</div> 2600<hr> 2601</div> 2602<div class="sect3"> 2603<h4 id="quat_minus"><code>operator-</code> (binary)</h4> 2604<div class="listingblock"> 2605<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2606<div class="content"> 2607<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2608 2609 //Only enabled if: 2610 // is_quat<A>::value && is_quat<B>::value 2611 template <class A,class B> 2612 typename deduce_quat2<A,B>::type 2613 operator-( A const & a, B const & b ); 2614 2615} }</code></pre> 2616</div> 2617</div> 2618<div class="dlist"> 2619<dl> 2620<dt class="hdlist1">Returns: </dt> 2621<dd> 2622<p>A quaternion with elements equal to the elements of <code>b</code> subtracted from the corresponding elements of <code>a</code>.</p> 2623</dd> 2624</dl> 2625</div> 2626<div class="admonitionblock note"> 2627<table> 2628<tr> 2629<td class="icon"> 2630<i class="fa icon-note" title="Note"></i> 2631</td> 2632<td class="content"> 2633The <a href="#deduce_quat2"><code>deduce_quat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 2634</td> 2635</tr> 2636</table> 2637</div> 2638<hr> 2639</div> 2640<div class="sect3"> 2641<h4 id="quat_plus_eq"><code>operator+=</code></h4> 2642<div class="listingblock"> 2643<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2644<div class="content"> 2645<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2646 2647 //Only enabled if: 2648 // is_quat<A>::value && is_quat<B>::value 2649 template <class A,class B> 2650 A & operator+=( A & a, B const & b ); 2651 2652} }</code></pre> 2653</div> 2654</div> 2655<div class="dlist"> 2656<dl> 2657<dt class="hdlist1">Effects: </dt> 2658<dd> 2659<p>Adds the elements of <code>b</code> to the corresponding elements of <code>a</code>.</p> 2660</dd> 2661<dt class="hdlist1">Returns: </dt> 2662<dd> 2663<p><code>a</code>.</p> 2664</dd> 2665</dl> 2666</div> 2667<hr> 2668</div> 2669<div class="sect3"> 2670<h4 id="quat_plus"><code>operator+</code></h4> 2671<div class="listingblock"> 2672<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2673<div class="content"> 2674<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2675 2676 //Only enabled if: 2677 // is_quat<A>::value && is_quat<B>::value && 2678 template <class A,class B> 2679 typename deduce_quat2<A,B>::type 2680 operator+( A const & a, B const & b ); 2681 2682} }</code></pre> 2683</div> 2684</div> 2685<div class="dlist"> 2686<dl> 2687<dt class="hdlist1">Returns: </dt> 2688<dd> 2689<p>A quaternion with elements equal to the elements of <code>a</code> added to the corresponding elements of <code>b</code>.</p> 2690</dd> 2691</dl> 2692</div> 2693<div class="admonitionblock note"> 2694<table> 2695<tr> 2696<td class="icon"> 2697<i class="fa icon-note" title="Note"></i> 2698</td> 2699<td class="content"> 2700The <a href="#deduce_quat2"><code>deduce_quat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 2701</td> 2702</tr> 2703</table> 2704</div> 2705<hr> 2706</div> 2707<div class="sect3"> 2708<h4 id="quat_div_eq_scalar"><code>operator/=</code> (scalar)</h4> 2709<div class="listingblock"> 2710<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2711<div class="content"> 2712<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2713 2714 //Only enabled if: is_quat<A>::value && is_scalar<B>::value 2715 template <class A,class B> 2716 A & operator/=( A & a, B b ); 2717 2718} }</code></pre> 2719</div> 2720</div> 2721<div class="dlist"> 2722<dl> 2723<dt class="hdlist1">Effects: </dt> 2724<dd> 2725<p>This operation divides a quaternion by a scalar.</p> 2726</dd> 2727<dt class="hdlist1">Returns: </dt> 2728<dd> 2729<p><code>a</code>.</p> 2730</dd> 2731</dl> 2732</div> 2733<hr> 2734</div> 2735<div class="sect3"> 2736<h4 id="quat_div_scalar"><code>operator/</code> (scalar)</h4> 2737<div class="listingblock"> 2738<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2739<div class="content"> 2740<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2741 2742 //Only enabled if: is_quat<A>::value && is_scalar<B>::value 2743 template <class A,class B> 2744 typename deduce_quat<A>::type 2745 operator/( A const & a, B b ); 2746 2747} }</code></pre> 2748</div> 2749</div> 2750<div class="dlist"> 2751<dl> 2752<dt class="hdlist1">Returns: </dt> 2753<dd> 2754<p>A quaternion that is the result of dividing the quaternion <code>a</code> by the scalar <code>b</code>.</p> 2755</dd> 2756</dl> 2757</div> 2758<div class="admonitionblock note"> 2759<table> 2760<tr> 2761<td class="icon"> 2762<i class="fa icon-note" title="Note"></i> 2763</td> 2764<td class="content"> 2765The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 2766</td> 2767</tr> 2768</table> 2769</div> 2770<hr> 2771</div> 2772<div class="sect3"> 2773<h4 id="quat_mul_eq_scalar"><code>operator*=</code> (scalar)</h4> 2774<div class="listingblock"> 2775<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2776<div class="content"> 2777<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2778 2779 //Only enabled if: is_quat<A>::value && is_scalar<B>::value 2780 template <class A,class B> 2781 A & operator*=( A & a, B b ); 2782 2783} }</code></pre> 2784</div> 2785</div> 2786<div class="dlist"> 2787<dl> 2788<dt class="hdlist1">Effects: </dt> 2789<dd> 2790<p>This operation multiplies the quaternion <code>a</code> by the scalar <code>b</code>.</p> 2791</dd> 2792<dt class="hdlist1">Returns: </dt> 2793<dd> 2794<p><code>a</code>.</p> 2795</dd> 2796</dl> 2797</div> 2798<hr> 2799</div> 2800<div class="sect3"> 2801<h4 id="quat_mul_eq"><code>operator*=</code></h4> 2802<div class="listingblock"> 2803<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2804<div class="content"> 2805<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2806 2807 //Only enabled if: 2808 // is_quat<A>::value && is_quat<B>::value 2809 template <class A,class B> 2810 A & operator*=( A & a, B const & b ); 2811 2812} }</code></pre> 2813</div> 2814</div> 2815<div class="dlist"> 2816<dl> 2817<dt class="hdlist1">Effects: </dt> 2818<dd> 2819<p>As if:</p> 2820<div class="listingblock"> 2821<div class="content"> 2822<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A tmp(a); 2823a = tmp * b; 2824return a;</code></pre> 2825</div> 2826</div> 2827</dd> 2828</dl> 2829</div> 2830<hr> 2831</div> 2832<div class="sect3"> 2833<h4 id="quat_mul_scalar"><code>operator*</code> (scalar)</h4> 2834<div class="listingblock"> 2835<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2836<div class="content"> 2837<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2838 2839 //Only enabled if: is_quat<A>::value && is_scalar<B>::value 2840 template <class A,class B> 2841 typename deduce_quat<A>::type 2842 operator*( A const & a, B b ); 2843 2844} }</code></pre> 2845</div> 2846</div> 2847<div class="dlist"> 2848<dl> 2849<dt class="hdlist1">Returns: </dt> 2850<dd> 2851<p>A quaternion that is the result of multiplying the quaternion <code>a</code> by the scalar <code>b</code>.</p> 2852</dd> 2853</dl> 2854</div> 2855<div class="admonitionblock note"> 2856<table> 2857<tr> 2858<td class="icon"> 2859<i class="fa icon-note" title="Note"></i> 2860</td> 2861<td class="content"> 2862The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 2863</td> 2864</tr> 2865</table> 2866</div> 2867<hr> 2868</div> 2869<div class="sect3"> 2870<h4 id="quat_mul"><code>operator*</code></h4> 2871<div class="listingblock"> 2872<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2873<div class="content"> 2874<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2875 2876 //Only enabled if: 2877 // is_quat<A>::value && is_quat<B>::value 2878 template <class A,class B> 2879 typename deduce_quat2<A,B>::type 2880 operator*( A const & a, B const & b ); 2881 2882} }</code></pre> 2883</div> 2884</div> 2885<div class="dlist"> 2886<dl> 2887<dt class="hdlist1">Returns: </dt> 2888<dd> 2889<p>The result of multiplying the quaternions <code>a</code> and <code>b</code>.</p> 2890</dd> 2891</dl> 2892</div> 2893<div class="admonitionblock note"> 2894<table> 2895<tr> 2896<td class="icon"> 2897<i class="fa icon-note" title="Note"></i> 2898</td> 2899<td class="content"> 2900The <a href="#deduce_quat2"><code>deduce_quat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 2901</td> 2902</tr> 2903</table> 2904</div> 2905<hr> 2906</div> 2907<div class="sect3"> 2908<h4 id="quat_eq"><code>operator==</code></h4> 2909<div class="listingblock"> 2910<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2911<div class="content"> 2912<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2913 2914 //Only enabled if: 2915 // is_quat<A>::value && is_quat<B>::value 2916 template <class A,class B> 2917 bool operator==( A const & a, B const & b ); 2918 2919} }</code></pre> 2920</div> 2921</div> 2922<div class="dlist"> 2923<dl> 2924<dt class="hdlist1">Returns: </dt> 2925<dd> 2926<p><code>true</code> if each element of <code>a</code> compares equal to its corresponding element of <code>b</code>, <code>false</code> otherwise.</p> 2927</dd> 2928</dl> 2929</div> 2930<hr> 2931</div> 2932<div class="sect3"> 2933<h4 id="quat_neq"><code>operator!=</code></h4> 2934<div class="listingblock"> 2935<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2936<div class="content"> 2937<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2938 2939 //Only enabled if: 2940 // is_quat<A>::value && is_quat<B>::value 2941 template <class A,class B> 2942 bool operator!=( A const & a, B const & b ); 2943 2944} }</code></pre> 2945</div> 2946</div> 2947<div class="dlist"> 2948<dl> 2949<dt class="hdlist1">Returns: </dt> 2950<dd> 2951<p><code>!(a == b)</code>.</p> 2952</dd> 2953</dl> 2954</div> 2955<hr> 2956</div> 2957<div class="sect3"> 2958<h4 id="quat_cmp"><code>cmp</code></h4> 2959<div class="listingblock"> 2960<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2961<div class="content"> 2962<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2963 2964 //Only enabled if: 2965 // is_quat<A>::value && is_quat<B>::value 2966 template <class A,class B,class Cmp> 2967 bool cmp( A const & a, B const & b, Cmp pred ); 2968 2969} }</code></pre> 2970</div> 2971</div> 2972<div class="dlist"> 2973<dl> 2974<dt class="hdlist1">Returns: </dt> 2975<dd> 2976<p>Similar to <a href="#quat_eq"><code>operator==</code></a>, except that it uses the binary predicate <code>pred</code> to compare the individual quaternion elements.</p> 2977</dd> 2978</dl> 2979</div> 2980<hr> 2981</div> 2982<div class="sect3"> 2983<h4 id="quat_mag_sqr"><code>mag_sqr</code></h4> 2984<div class="listingblock"> 2985<div class="title">#include <boost/qvm/quat_operations.hpp></div> 2986<div class="content"> 2987<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 2988 2989 //Only enabled if: is_quat<A>::value 2990 template <class A> 2991 typename quat_traits<A>::scalar_type 2992 mag_sqr( A const & a ); 2993 2994} }</code></pre> 2995</div> 2996</div> 2997<div class="dlist"> 2998<dl> 2999<dt class="hdlist1">Returns: </dt> 3000<dd> 3001<p>The squared magnitude of the quaternion <code>a</code>.</p> 3002</dd> 3003</dl> 3004</div> 3005<hr> 3006</div> 3007<div class="sect3"> 3008<h4 id="quat_mag"><code>mag</code></h4> 3009<div class="listingblock"> 3010<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3011<div class="content"> 3012<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3013 3014 //Only enabled if: is_quat<A>::value 3015 template <class A> 3016 typename quat_traits<A>::scalar_type 3017 mag( A const & a ); 3018 3019} }</code></pre> 3020</div> 3021</div> 3022<div class="dlist"> 3023<dl> 3024<dt class="hdlist1">Returns: </dt> 3025<dd> 3026<p>The magnitude of the quaternion <code>a</code>.</p> 3027</dd> 3028</dl> 3029</div> 3030<hr> 3031</div> 3032<div class="sect3"> 3033<h4 id="quat_normalized"><code>normalized</code></h4> 3034<div class="listingblock"> 3035<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3036<div class="content"> 3037<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3038 3039 //Only enabled if: is_quat<A>::value 3040 template <class A> 3041 typename deduce_quat<A>::type 3042 normalized( A const & a ); 3043 3044} }</code></pre> 3045</div> 3046</div> 3047<div class="dlist"> 3048<dl> 3049<dt class="hdlist1">Effects: </dt> 3050<dd> 3051<p>As if:</p> 3052<div class="listingblock"> 3053<div class="content"> 3054<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">typename deduce_quat<A>::type tmp; 3055assign(tmp,a); 3056normalize(tmp); 3057return tmp;</code></pre> 3058</div> 3059</div> 3060</dd> 3061</dl> 3062</div> 3063<div class="admonitionblock note"> 3064<table> 3065<tr> 3066<td class="icon"> 3067<i class="fa icon-note" title="Note"></i> 3068</td> 3069<td class="content"> 3070The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 3071</td> 3072</tr> 3073</table> 3074</div> 3075<hr> 3076</div> 3077<div class="sect3"> 3078<h4 id="quat_normalize"><code>normalize</code></h4> 3079<div class="listingblock"> 3080<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3081<div class="content"> 3082<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3083 3084 //Only enabled if: is_quat<A>::value 3085 template <class A> 3086 void normalize( A & a ); 3087 3088} }</code></pre> 3089</div> 3090</div> 3091<div class="dlist"> 3092<dl> 3093<dt class="hdlist1">Effects: </dt> 3094<dd> 3095<p>Normalizes <code>a</code>.</p> 3096</dd> 3097<dt class="hdlist1">Ensures: </dt> 3098<dd> 3099<p><code>mag(a)==scalar_traits<typename quat_traits<A>::scalar_type>::value(1).</code></p> 3100</dd> 3101<dt class="hdlist1">Throws: </dt> 3102<dd> 3103<p>If the magnitude of <code>a</code> is zero, throws <a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a>.</p> 3104</dd> 3105</dl> 3106</div> 3107<hr> 3108</div> 3109<div class="sect3"> 3110<h4 id="quat_dot"><code>dot</code></h4> 3111<div class="listingblock"> 3112<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3113<div class="content"> 3114<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3115 3116 //Only enabled if: 3117 // is_quat<A>::value && is_quat<B>::value 3118 template <class A,class B> 3119 typename deduce_scalar<A,B>::type 3120 dot( A const & a, B const & b ); 3121 3122} }</code></pre> 3123</div> 3124</div> 3125<div class="dlist"> 3126<dl> 3127<dt class="hdlist1">Returns: </dt> 3128<dd> 3129<p>The dot product of the quaternions <code>a</code> and <code>b</code>.</p> 3130</dd> 3131</dl> 3132</div> 3133<div class="admonitionblock note"> 3134<table> 3135<tr> 3136<td class="icon"> 3137<i class="fa icon-note" title="Note"></i> 3138</td> 3139<td class="content"> 3140The <a href="#deduce_scalar"><code>deduce_scalar</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 3141</td> 3142</tr> 3143</table> 3144</div> 3145<hr> 3146</div> 3147<div class="sect3"> 3148<h4 id="conjugate"><code>conjugate</code></h4> 3149<div class="listingblock"> 3150<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3151<div class="content"> 3152<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3153 3154 //Only enabled if: is_quat<A>::value 3155 template <class A> 3156 typename deduce_quat<A>::type 3157 conjugate( A const & a ); 3158 3159} }</code></pre> 3160</div> 3161</div> 3162<div class="dlist"> 3163<dl> 3164<dt class="hdlist1">Returns: </dt> 3165<dd> 3166<p>Computes the conjugate of <code>a</code>.</p> 3167</dd> 3168</dl> 3169</div> 3170<div class="admonitionblock note"> 3171<table> 3172<tr> 3173<td class="icon"> 3174<i class="fa icon-note" title="Note"></i> 3175</td> 3176<td class="content"> 3177The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 3178</td> 3179</tr> 3180</table> 3181</div> 3182<hr> 3183</div> 3184<div class="sect3"> 3185<h4 id="quat_inverse"><code>inverse</code></h4> 3186<div class="listingblock"> 3187<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3188<div class="content"> 3189<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3190 3191 //Only enabled if: is_quat<A>::value 3192 template <class A> 3193 typename deduce_quat<A>::type 3194 inverse( A const & a ); 3195 3196} }</code></pre> 3197</div> 3198</div> 3199<div class="dlist"> 3200<dl> 3201<dt class="hdlist1">Returns: </dt> 3202<dd> 3203<p>Computes the multiplicative inverse of <code>a</code>, or the conjugate-to-norm ratio.</p> 3204</dd> 3205<dt class="hdlist1">Throws: </dt> 3206<dd> 3207<p>If the magnitude of <code>a</code> is zero, throws <a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a>.</p> 3208</dd> 3209</dl> 3210</div> 3211<div class="admonitionblock tip"> 3212<table> 3213<tr> 3214<td class="icon"> 3215<i class="fa icon-tip" title="Tip"></i> 3216</td> 3217<td class="content"> 3218If <code>a</code> is known to be unit length, <code>conjugate</code> is equivalent to <a href="#quat_inverse"><code>inverse</code></a>, yet it is faster to compute. 3219</td> 3220</tr> 3221</table> 3222</div> 3223<div class="admonitionblock note"> 3224<table> 3225<tr> 3226<td class="icon"> 3227<i class="fa icon-note" title="Note"></i> 3228</td> 3229<td class="content"> 3230The <a href="#deduce_quat"><code>deduce_quat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 3231</td> 3232</tr> 3233</table> 3234</div> 3235<hr> 3236</div> 3237<div class="sect3"> 3238<h4 id="slerp"><code>slerp</code></h4> 3239<div class="listingblock"> 3240<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3241<div class="content"> 3242<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3243 3244 //Only enabled if: 3245 // is_quat<A>::value && is_quat<B>::value && is_scalar<C> 3246 template <class A,class B,class C> 3247 typename deduce_quat2<A,B> >::type 3248 slerp( A const & a, B const & b, C c ); 3249 3250} }</code></pre> 3251</div> 3252</div> 3253<div class="dlist"> 3254<dl> 3255<dt class="hdlist1">Preconditions: </dt> 3256<dd> 3257<p><code>t>=0 && t<=1</code>.</p> 3258</dd> 3259<dt class="hdlist1">Returns: </dt> 3260<dd> 3261<p>A quaternion that is the result of Spherical Linear Interpolation of the quaternions <code>a</code> and <code>b</code> and the interpolation parameter <code>c</code>. When <code>slerp</code> 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.</p> 3262</dd> 3263</dl> 3264</div> 3265<div class="admonitionblock note"> 3266<table> 3267<tr> 3268<td class="icon"> 3269<i class="fa icon-note" title="Note"></i> 3270</td> 3271<td class="content"> 3272The <a href="#deduce_quat2"><code>deduce_quat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 3273</td> 3274</tr> 3275</table> 3276</div> 3277<hr> 3278</div> 3279<div class="sect3"> 3280<h4 id="zero_quat"><code>zero_quat</code></h4> 3281<div class="listingblock"> 3282<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3283<div class="content"> 3284<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3285 3286 template <class T> 3287 -unspecified-return-type- zero_quat(); 3288 3289} }</code></pre> 3290</div> 3291</div> 3292<div class="dlist"> 3293<dl> 3294<dt class="hdlist1">Returns: </dt> 3295<dd> 3296<p>A read-only quaternion of unspecified type with <a href="#scalar_traits"><code>scalar_type</code></a> <code>T</code>, with all elements equal to <a href="#scalar_traits"><code>scalar_traits<T>::value(0)</code></a>.</p> 3297</dd> 3298</dl> 3299</div> 3300<hr> 3301</div> 3302<div class="sect3"> 3303<h4 id="quat_set_zero"><code>set_zero</code></h4> 3304<div class="listingblock"> 3305<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3306<div class="content"> 3307<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3308 3309 //Only enabled if: is_quat<A>::value 3310 template <class A> 3311 void set_zero( A & a ); 3312 3313} }</code></pre> 3314</div> 3315</div> 3316<div class="dlist"> 3317<dl> 3318<dt class="hdlist1">Effects: </dt> 3319<dd> 3320<p>As if:</p> 3321<div class="listingblock"> 3322<div class="content"> 3323<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign(a, 3324 zero_quat<typename quat_traits<A>::scalar_type>());</code></pre> 3325</div> 3326</div> 3327</dd> 3328</dl> 3329</div> 3330<hr> 3331</div> 3332<div class="sect3"> 3333<h4 id="identity_quat"><code>identity_quat</code></h4> 3334<div class="listingblock"> 3335<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3336<div class="content"> 3337<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3338 3339 template <class S> 3340 -unspecified-return-type- identity_quat(); 3341 3342} }</code></pre> 3343</div> 3344</div> 3345<div class="dlist"> 3346<dl> 3347<dt class="hdlist1">Returns: </dt> 3348<dd> 3349<p>An identity quaternion with scalar type <code>S</code>.</p> 3350</dd> 3351</dl> 3352</div> 3353<hr> 3354</div> 3355<div class="sect3"> 3356<h4 id="quat_set_identity"><code>set_identity</code></h4> 3357<div class="listingblock"> 3358<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3359<div class="content"> 3360<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3361 3362 //Only enabled if: is_quat<A>::value 3363 template <class A> 3364 void set_identity( A & a ); 3365 3366} }</code></pre> 3367</div> 3368</div> 3369<div class="dlist"> 3370<dl> 3371<dt class="hdlist1">Effects: </dt> 3372<dd> 3373<p>As if:</p> 3374<div class="listingblock"> 3375<div class="content"> 3376<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 3377 a, 3378 identity_quat<typename quat_traits<A>::scalar_type>());</code></pre> 3379</div> 3380</div> 3381</dd> 3382</dl> 3383</div> 3384<hr> 3385</div> 3386<div class="sect3"> 3387<h4 id="rot_quat"><code>rot_quat</code></h4> 3388<div class="listingblock"> 3389<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3390<div class="content"> 3391<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3392 3393 //Only enabled if: 3394 // is_vec<A>::value && vec_traits<A>::dim==3 3395 template <class A> 3396 -unspecified-return-type- rot_quat( A const & axis, typename vec_traits<A>::scalar_type angle ); 3397 3398} }</code></pre> 3399</div> 3400</div> 3401<div class="dlist"> 3402<dl> 3403<dt class="hdlist1">Returns: </dt> 3404<dd> 3405<p>A quaternion of unspecified type which performs a rotation around the <code>axis</code> at <code>angle</code> radians.</p> 3406</dd> 3407<dt class="hdlist1">Throws: </dt> 3408<dd> 3409<p>In case the axis vector has zero magnitude, throws <a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a>.</p> 3410</dd> 3411</dl> 3412</div> 3413<div class="admonitionblock note"> 3414<table> 3415<tr> 3416<td class="icon"> 3417<i class="fa icon-note" title="Note"></i> 3418</td> 3419<td class="content"> 3420The <code>rot_quat</code> function is not a <a href="#view_proxy">view proxy</a>; it returns a temp object. 3421</td> 3422</tr> 3423</table> 3424</div> 3425<hr> 3426</div> 3427<div class="sect3"> 3428<h4 id="quat_set_rot"><code>set_rot</code></h4> 3429<div class="listingblock"> 3430<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3431<div class="content"> 3432<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3433 3434 //Only enabled if: 3435 // is_quat<A>::value && 3436 // is_vec<B>::value && vec_traits<B>::dim==3 3437 template <class A> 3438 void set_rot( A & a, B const & axis, typename vec_traits<B>::scalar_type angle ); 3439 3440} }</code></pre> 3441</div> 3442</div> 3443<div class="dlist"> 3444<dl> 3445<dt class="hdlist1">Effects: </dt> 3446<dd> 3447<p>As if:</p> 3448<div class="listingblock"> 3449<div class="content"> 3450<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 3451 a, 3452 rot_quat(axis,angle));</code></pre> 3453</div> 3454</div> 3455</dd> 3456</dl> 3457</div> 3458<hr> 3459</div> 3460<div class="sect3"> 3461<h4 id="quat_rotate"><code>rotate</code></h4> 3462<div class="listingblock"> 3463<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3464<div class="content"> 3465<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3466 3467 //Only enabled if: 3468 // is_quat<A>::value && 3469 // is_vec<B>::value && vec_traits<B>::dim==3 3470 template <class A,class B> 3471 void rotate( A & a, B const & axis, typename quat_traits<A>::scalar_type angle ); 3472 3473} }</code></pre> 3474</div> 3475</div> 3476<div class="dlist"> 3477<dl> 3478<dt class="hdlist1">Effects: </dt> 3479<dd> 3480<p>As if: <code>a *= <a href="#rot_quat">rot_quat</a>(axis,angle)</code>.</p> 3481</dd> 3482</dl> 3483</div> 3484<hr> 3485</div> 3486<div class="sect3"> 3487<h4 id="rotx_quat"><code>rotx_quat</code></h4> 3488<div class="listingblock"> 3489<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3490<div class="content"> 3491<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3492 3493 template <class Angle> 3494 -unspecified-return-type- rotx_quat( Angle const & angle ); 3495 3496} }</code></pre> 3497</div> 3498</div> 3499<div class="dlist"> 3500<dl> 3501<dt class="hdlist1">Returns: </dt> 3502<dd> 3503<p>A <a href="#view_proxy">view proxy</a> quaternion of unspecified type and scalar type <code>Angle</code>, which performs a rotation around the X axis at <code>angle</code> radians.</p> 3504</dd> 3505</dl> 3506</div> 3507<hr> 3508</div> 3509<div class="sect3"> 3510<h4 id="quat_set_rotx"><code>set_rotx</code></h4> 3511<div class="listingblock"> 3512<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3513<div class="content"> 3514<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3515 3516 //Only enabled if: is_quat<A>::value 3517 template <class A> 3518 void set_rotx( A & a, typename quat_traits<A>::scalar_type angle ); 3519 3520} }</code></pre> 3521</div> 3522</div> 3523<div class="dlist"> 3524<dl> 3525<dt class="hdlist1">Effects: </dt> 3526<dd> 3527<p>As if:</p> 3528<div class="listingblock"> 3529<div class="content"> 3530<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 3531 a, 3532 rotx_quat(angle));</code></pre> 3533</div> 3534</div> 3535</dd> 3536</dl> 3537</div> 3538<hr> 3539</div> 3540<div class="sect3"> 3541<h4 id="quat_rotate_x"><code>rotate_x</code></h4> 3542<div class="listingblock"> 3543<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3544<div class="content"> 3545<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3546 3547 //Only enabled if: is_quat<A>::value 3548 template <class A> 3549 void rotate_x( A & a, typename quat_traits<A>::scalar_type angle ); 3550 3551} }</code></pre> 3552</div> 3553</div> 3554<div class="dlist"> 3555<dl> 3556<dt class="hdlist1">Effects: </dt> 3557<dd> 3558<p>As if: <code>a *= <a href="#rotx_quat">rotx_quat</a>(angle)</code>.</p> 3559</dd> 3560</dl> 3561</div> 3562<hr> 3563</div> 3564<div class="sect3"> 3565<h4 id="roty_quat"><code>roty_quat</code></h4> 3566<div class="listingblock"> 3567<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3568<div class="content"> 3569<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3570 3571 template <class Angle> 3572 -unspecified-return-type- roty_quat( Angle const & angle ); 3573 3574} }</code></pre> 3575</div> 3576</div> 3577<div class="dlist"> 3578<dl> 3579<dt class="hdlist1">Returns: </dt> 3580<dd> 3581<p>A <a href="#view_proxy">view proxy</a> quaternion of unspecified type and scalar type <code>Angle</code>, which performs a rotation around the Y axis at <code>angle</code> radians.</p> 3582</dd> 3583</dl> 3584</div> 3585<hr> 3586</div> 3587<div class="sect3"> 3588<h4 id="quat_set_roty"><code>set_roty</code></h4> 3589<div class="listingblock"> 3590<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3591<div class="content"> 3592<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3593 3594 //Only enabled if: is_quat<A>::value 3595 template <class A> 3596 void set_rotz( A & a, typename quat_traits<A>::scalar_type angle ); 3597 3598} }</code></pre> 3599</div> 3600</div> 3601<div class="dlist"> 3602<dl> 3603<dt class="hdlist1">Effects: </dt> 3604<dd> 3605<p>As if:</p> 3606<div class="listingblock"> 3607<div class="content"> 3608<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 3609 a, 3610 roty_quat(angle));</code></pre> 3611</div> 3612</div> 3613</dd> 3614</dl> 3615</div> 3616<hr> 3617</div> 3618<div class="sect3"> 3619<h4 id="quat_rotate_y"><code>rotate_y</code></h4> 3620<div class="listingblock"> 3621<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3622<div class="content"> 3623<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3624 3625 //Only enabled if: is_quat<A>::value 3626 template <class A> 3627 void rotate_y( A & a, typename quat_traits<A>::scalar_type angle ); 3628 3629} }</code></pre> 3630</div> 3631</div> 3632<div class="dlist"> 3633<dl> 3634<dt class="hdlist1">Effects: </dt> 3635<dd> 3636<p>As if: <code>a *= <a href="#roty_quat">roty_quat</a>(angle)</code>.</p> 3637</dd> 3638</dl> 3639</div> 3640<hr> 3641</div> 3642<div class="sect3"> 3643<h4 id="rotz_quat"><code>rotz_quat</code></h4> 3644<div class="listingblock"> 3645<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3646<div class="content"> 3647<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3648 3649 template <class Angle> 3650 -unspecified-return-type- rotz_quat( Angle const & angle ); 3651 3652} }</code></pre> 3653</div> 3654</div> 3655<div class="dlist"> 3656<dl> 3657<dt class="hdlist1">Returns: </dt> 3658<dd> 3659<p>A <a href="#view_proxy">view proxy</a> quaternion of unspecified type and scalar type <code>Angle</code>, which performs a rotation around the Z axis at <code>angle</code> radians.</p> 3660</dd> 3661</dl> 3662</div> 3663<hr> 3664</div> 3665<div class="sect3"> 3666<h4 id="quat_set_rotz"><code>set_rotz</code></h4> 3667<div class="listingblock"> 3668<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3669<div class="content"> 3670<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3671 3672 //Only enabled if: is_quat<A>::value 3673 template <class A> 3674 void set_rotz( A & a, typename quat_traits<A>::scalar_type angle ); 3675 3676} }</code></pre> 3677</div> 3678</div> 3679<div class="dlist"> 3680<dl> 3681<dt class="hdlist1">Effects: </dt> 3682<dd> 3683<p>As if:</p> 3684<div class="listingblock"> 3685<div class="content"> 3686<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 3687 a, 3688 rotz_quat(angle));</code></pre> 3689</div> 3690</div> 3691</dd> 3692</dl> 3693</div> 3694<hr> 3695</div> 3696<div class="sect3"> 3697<h4 id="quat_rotate_z"><code>rotate_z</code></h4> 3698<div class="listingblock"> 3699<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3700<div class="content"> 3701<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3702 3703 //Only enabled if: is_quat<A>::value 3704 template <class A> 3705 void rotate_z( A & a, typename quat_traits<A>::scalar_type angle ); 3706 3707} }</code></pre> 3708</div> 3709</div> 3710<div class="dlist"> 3711<dl> 3712<dt class="hdlist1">Effects: </dt> 3713<dd> 3714<p>As if: <code>a *= <a href="#rotz_quat">rotz_quat</a>(angle)</code>.</p> 3715</dd> 3716</dl> 3717</div> 3718<hr> 3719</div> 3720<div class="sect3"> 3721<h4 id="quat_scalar_cast"><code>scalar_cast</code></h4> 3722<div class="listingblock"> 3723<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3724<div class="content"> 3725<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3726 3727 //Only enabled if: is_quat<A>::value 3728 template <class Scalar,class A> 3729 -unspecified-return_type- scalar_cast( A const & a ); 3730 3731} }</code></pre> 3732</div> 3733</div> 3734<div class="dlist"> 3735<dl> 3736<dt class="hdlist1">Returns: </dt> 3737<dd> 3738<p>A read-only <a href="#view_proxy">view proxy</a> of <code>a</code> that looks like a quaternion of the same dimensions as <code>a</code>, but with <a href="#quat_traits"><code>scalar_type</code></a> <code>Scalar</code> and elements constructed from the corresponding elements of <code>a</code>.</p> 3739</dd> 3740</dl> 3741</div> 3742<hr> 3743</div> 3744<div class="sect3"> 3745<h4 id="qref"><code>qref</code></h4> 3746<div class="listingblock"> 3747<div class="title">#include <boost/qvm/quat_operations.hpp></div> 3748<div class="content"> 3749<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3750 3751 //Only enabled if: is_quat<A>::value 3752 template <class A> 3753 -unspecified-return-type- qref( A & a ); 3754 3755} }</code></pre> 3756</div> 3757</div> 3758<div class="dlist"> 3759<dl> 3760<dt class="hdlist1">Returns: </dt> 3761<dd> 3762<p>An identity view proxy of <code>a</code>; that is, it simply accesses the elements of <code>a</code>.</p> 3763</dd> 3764</dl> 3765</div> 3766<div class="admonitionblock tip"> 3767<table> 3768<tr> 3769<td class="icon"> 3770<i class="fa icon-tip" title="Tip"></i> 3771</td> 3772<td class="content"> 3773<code>qref</code> allows calling QVM operations when <code>a</code> is of built-in type, for example a plain old C array. 3774</td> 3775</tr> 3776</table> 3777</div> 3778<hr> 3779</div> 3780</div> 3781<div class="sect2"> 3782<h3 id="_vector_operations">Vector Operations</h3> 3783<div class="sect3"> 3784<h4 id="vec_assign"><code>assign</code></h4> 3785<div class="listingblock"> 3786<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3787<div class="content"> 3788<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3789 3790 //Only enabled if: 3791 // is_vec<A>::value && is_vec<B>::value && 3792 // vec_traits<A>::dim==vec_traits<B>::dim 3793 template <class A,class B> 3794 A & assign( A & a, B const & b ); 3795 3796} }</code></pre> 3797</div> 3798</div> 3799<div class="dlist"> 3800<dl> 3801<dt class="hdlist1">Effects: </dt> 3802<dd> 3803<p>Copies all elements of the vector <code>b</code> to the vector <code>a</code>.</p> 3804</dd> 3805<dt class="hdlist1">Returns: </dt> 3806<dd> 3807<p><code>a</code>.</p> 3808</dd> 3809</dl> 3810</div> 3811<hr> 3812</div> 3813<div class="sect3"> 3814<h4 id="vec_convert_to"><code>convert_to</code></h4> 3815<div class="listingblock"> 3816<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3817<div class="content"> 3818<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3819 3820 //Only enabled if: 3821 // is_vec<R>::value && is_vec<A>::value && 3822 // vec_traits<R>::dim==vec_traits<A>::dim 3823 template <class R,class A> 3824 R convert_to( A const & a ); 3825 3826} }</code></pre> 3827</div> 3828</div> 3829<div class="dlist"> 3830<dl> 3831<dt class="hdlist1">Requires: </dt> 3832<dd> 3833<p><code>R</code> must be copyable.</p> 3834</dd> 3835<dt class="hdlist1">Effects: </dt> 3836<dd> 3837<p>As if: <code>R r; assign(r,a); return r;</code></p> 3838</dd> 3839</dl> 3840</div> 3841<hr> 3842</div> 3843<div class="sect3"> 3844<h4 id="vec_minus_eq"><code>operator-=</code></h4> 3845<div class="listingblock"> 3846<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3847<div class="content"> 3848<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3849 3850 //Only enabled if: 3851 // is_vec<A>::value && is_vec<B>::value && 3852 // vec_traits<A>::dim==vec_traits<B>::dim 3853 template <class A,class B> 3854 A & operator-=( A & a, B const & b ); 3855 3856} }</code></pre> 3857</div> 3858</div> 3859<div class="dlist"> 3860<dl> 3861<dt class="hdlist1">Effects: </dt> 3862<dd> 3863<p>Subtracts the elements of <code>b</code> from the corresponding elements of <code>a</code>.</p> 3864</dd> 3865<dt class="hdlist1">Returns: </dt> 3866<dd> 3867<p><code>a</code>.</p> 3868</dd> 3869</dl> 3870</div> 3871<hr> 3872</div> 3873<div class="sect3"> 3874<h4 id="vec_minus_unary"><code>operator-</code> (unary)</h4> 3875<div class="paragraph"> 3876<p>operator-(vec)</p> 3877</div> 3878<div class="listingblock"> 3879<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3880<div class="content"> 3881<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3882 3883 //Only enabled if: is_vec<A>::value 3884 template <class A> 3885 typename deduce_vec<A>::type 3886 operator-( A const & a ); 3887 3888} }</code></pre> 3889</div> 3890</div> 3891<div class="dlist"> 3892<dl> 3893<dt class="hdlist1">Returns: </dt> 3894<dd> 3895<p>A vector of the negated elements of <code>a</code>.</p> 3896</dd> 3897</dl> 3898</div> 3899<div class="admonitionblock note"> 3900<table> 3901<tr> 3902<td class="icon"> 3903<i class="fa icon-note" title="Note"></i> 3904</td> 3905<td class="content"> 3906The <a href="#deduce_vec"><code>deduce_vec</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 3907</td> 3908</tr> 3909</table> 3910</div> 3911<hr> 3912</div> 3913<div class="sect3"> 3914<h4 id="vec_minus"><code>operator-</code> (binary)</h4> 3915<div class="listingblock"> 3916<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3917<div class="content"> 3918<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3919 3920 //Only enabled if: 3921 // is_vec<A>::value && is_vec<B>::value && 3922 // vec_traits<A>::dim==vec_traits<B>::dim 3923 template <class A,class B> 3924 typename deduce_vec2<A,B,vec_traits<A>::dim>::type 3925 operator-( A const & a, B const & b ); 3926 3927} }</code></pre> 3928</div> 3929</div> 3930<div class="dlist"> 3931<dl> 3932<dt class="hdlist1">Returns: </dt> 3933<dd> 3934<p>A vector of the same size as <code>a</code> and <code>b</code>, with elements the elements of <code>b</code> subtracted from the corresponding elements of <code>a</code>.</p> 3935</dd> 3936</dl> 3937</div> 3938<div class="admonitionblock note"> 3939<table> 3940<tr> 3941<td class="icon"> 3942<i class="fa icon-note" title="Note"></i> 3943</td> 3944<td class="content"> 3945The <a href="#deduce_vec2"><code>deduce_vec2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 3946</td> 3947</tr> 3948</table> 3949</div> 3950<hr> 3951</div> 3952<div class="sect3"> 3953<h4 id="vec_plus_eq"><code>operator+=</code></h4> 3954<div class="listingblock"> 3955<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3956<div class="content"> 3957<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3958 3959 //Only enabled if: 3960 // is_vec<A>::value && is_vec<B>::value && 3961 // vec_traits<A>::dim==vec_traits<B>::dim 3962 template <class A,class B> 3963 A & operator+=( A & a, B const & b ); 3964 3965} }</code></pre> 3966</div> 3967</div> 3968<div class="dlist"> 3969<dl> 3970<dt class="hdlist1">Effects: </dt> 3971<dd> 3972<p>Adds the elements of <code>b</code> to the corresponding elements of <code>a</code>.</p> 3973</dd> 3974<dt class="hdlist1">Returns: </dt> 3975<dd> 3976<p><code>a</code>.</p> 3977</dd> 3978</dl> 3979</div> 3980<hr> 3981</div> 3982<div class="sect3"> 3983<h4 id="vec_plus"><code>operator+</code></h4> 3984<div class="listingblock"> 3985<div class="title">#include <boost/qvm/vec_operations.hpp></div> 3986<div class="content"> 3987<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 3988 3989 //Only enabled if: 3990 // is_vec<A>::value && is_vec<B>::value && 3991 // vec_traits<A>::dim==vec_traits<B>::dim 3992 template <class A,class B> 3993 typename deduce_vec2<A,B,vec_traits<A>::dim>::type 3994 operator+( A const & a, B const & b ); 3995 3996} }</code></pre> 3997</div> 3998</div> 3999<div class="dlist"> 4000<dl> 4001<dt class="hdlist1">Returns: </dt> 4002<dd> 4003<p>A vector of the same size as <code>a</code> and <code>b</code>, with elements the elements of <code>b</code> added to the corresponding elements of <code>a</code>.</p> 4004</dd> 4005</dl> 4006</div> 4007<div class="admonitionblock note"> 4008<table> 4009<tr> 4010<td class="icon"> 4011<i class="fa icon-note" title="Note"></i> 4012</td> 4013<td class="content"> 4014The <a href="#deduce_vec2"><code>deduce_vec2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4015</td> 4016</tr> 4017</table> 4018</div> 4019<hr> 4020</div> 4021<div class="sect3"> 4022<h4 id="vec_div_eq_scalar"><code>operator/=</code> (scalar)</h4> 4023<div class="listingblock"> 4024<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4025<div class="content"> 4026<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4027 4028 //Only enabled if: is_vec<A>::value && is_scalar<B>::value 4029 template <class A,class B> 4030 A & operator/=( A & a, B b ); 4031 4032} }</code></pre> 4033</div> 4034</div> 4035<div class="dlist"> 4036<dl> 4037<dt class="hdlist1">Effects: </dt> 4038<dd> 4039<p>This operation divides a vector by a scalar.</p> 4040</dd> 4041<dt class="hdlist1">Returns: </dt> 4042<dd> 4043<p><code>a</code>.</p> 4044</dd> 4045</dl> 4046</div> 4047<hr> 4048</div> 4049<div class="sect3"> 4050<h4 id="vec_div_scalar"><code>operator/</code></h4> 4051<div class="listingblock"> 4052<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4053<div class="content"> 4054<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4055 4056 //Only enabled if: is_vec<A>::value && is_scalar<B>::value 4057 template <class A,class B> 4058 typename deduce_vec<A>::type 4059 operator/( A const & a, B b ); 4060 4061} }</code></pre> 4062</div> 4063</div> 4064<div class="dlist"> 4065<dl> 4066<dt class="hdlist1">Returns: </dt> 4067<dd> 4068<p>A vector that is the result of dividing the vector <code>a</code> by the scalar <code>b</code>.</p> 4069</dd> 4070</dl> 4071</div> 4072<div class="admonitionblock note"> 4073<table> 4074<tr> 4075<td class="icon"> 4076<i class="fa icon-note" title="Note"></i> 4077</td> 4078<td class="content"> 4079The <a href="#deduce_vec"><code>deduce_vec</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 4080</td> 4081</tr> 4082</table> 4083</div> 4084<hr> 4085</div> 4086<div class="sect3"> 4087<h4 id="vec_mul_eq_scalar"><code>operator*=</code></h4> 4088<div class="listingblock"> 4089<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4090<div class="content"> 4091<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4092 4093 //Only enabled if: is_vec<A>::value && is_scalar<B>::value 4094 template <class A,class B> 4095 A & operator*=( A & a, B b ); 4096 4097} }</code></pre> 4098</div> 4099</div> 4100<div class="dlist"> 4101<dl> 4102<dt class="hdlist1">Effects: </dt> 4103<dd> 4104<p>This operation multiplies the vector <code>a</code> by the scalar <code>b</code>.</p> 4105</dd> 4106<dt class="hdlist1">Returns: </dt> 4107<dd> 4108<p><code>a</code>.</p> 4109</dd> 4110</dl> 4111</div> 4112<hr> 4113</div> 4114<div class="sect3"> 4115<h4 id="vec_mul_scalar"><code>operator*</code></h4> 4116<div class="listingblock"> 4117<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4118<div class="content"> 4119<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4120 4121 //Only enabled if: is_vec<A>::value && is_scalar<B>::value 4122 template <class A> 4123 typename deduce_vec<A>::type 4124 operator*( A const & a, B b ); 4125 4126} }</code></pre> 4127</div> 4128</div> 4129<div class="dlist"> 4130<dl> 4131<dt class="hdlist1">Returns: </dt> 4132<dd> 4133<p>A vector that is the result of multiplying the vector <code>a</code> by the scalar <code>b</code>.</p> 4134</dd> 4135</dl> 4136</div> 4137<div class="admonitionblock note"> 4138<table> 4139<tr> 4140<td class="icon"> 4141<i class="fa icon-note" title="Note"></i> 4142</td> 4143<td class="content"> 4144The <a href="#deduce_vec"><code>deduce_vec</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 4145</td> 4146</tr> 4147</table> 4148</div> 4149<hr> 4150</div> 4151<div class="sect3"> 4152<h4 id="vec_eq"><code>operator==</code></h4> 4153<div class="listingblock"> 4154<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4155<div class="content"> 4156<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4157 4158 //Only enabled if: 4159 // is_vec<A>::value && is_vec<B>::value && 4160 // vec_traits<A>::dim==vec_traits<B>::dim 4161 template <class A,class B> 4162 bool operator==( A const & a, B const & b ); 4163 4164} }</code></pre> 4165</div> 4166</div> 4167<div class="dlist"> 4168<dl> 4169<dt class="hdlist1">Returns: </dt> 4170<dd> 4171<p><code>true</code> if each element of <code>a</code> compares equal to its corresponding element of <code>b</code>, <code>false</code> otherwise.</p> 4172</dd> 4173</dl> 4174</div> 4175<hr> 4176</div> 4177<div class="sect3"> 4178<h4 id="vec_neq"><code>operator!=</code></h4> 4179<div class="listingblock"> 4180<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4181<div class="content"> 4182<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4183 4184 //Only enabled if: 4185 // is_vec<A>::value && is_vec<B>::value && 4186 // vec_traits<A>::dim==vec_traits<B>::dim 4187 template <class A,class B> 4188 bool operator!=( A const & a, B const & b ); 4189 4190} }</code></pre> 4191</div> 4192</div> 4193<div class="dlist"> 4194<dl> 4195<dt class="hdlist1">Returns: </dt> 4196<dd> 4197<p><code>!(a == b)</code>.</p> 4198</dd> 4199</dl> 4200</div> 4201<hr> 4202</div> 4203<div class="sect3"> 4204<h4 id="vec_cmp"><code>cmp</code></h4> 4205<div class="listingblock"> 4206<div class="content"> 4207<pre class="nowrap">.#include <boost/qvm/mat_operations.hpp> 4208 4209namespace boost 4210{ 4211 namespace qvm 4212 { 4213 //Only enabled if: 4214 // is_mat<A>::value && is_mat<B>::value && 4215 // mat_traits<A>::rows==mat_traits<B>::rows && 4216 // mat_traits<A>::cols==mat_traits<B>::cols 4217 template <class A,class B,class Cmp> 4218 bool cmp( A const & a, B const & b, Cmp pred ); 4219 4220} }</pre> 4221</div> 4222</div> 4223<div class="dlist"> 4224<dl> 4225<dt class="hdlist1">Returns: </dt> 4226<dd> 4227<p>Similar to <a href="#vec_eq"><code>operator==</code></a>, except that the individual elements of <code>a</code> and <code>b</code> are passed to the binary predicate <code>pred</code> for comparison.</p> 4228</dd> 4229</dl> 4230</div> 4231<hr> 4232</div> 4233<div class="sect3"> 4234<h4 id="vec_mag_sqr"><code>mag_sqr</code></h4> 4235<div class="listingblock"> 4236<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4237<div class="content"> 4238<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4239 4240 //Only enabled if: 4241 // is_vec<A>::value 4242 template <class A> 4243 typename vec_traits<A>::scalar_type 4244 mag_sqr( A const & a ); 4245 4246} }</code></pre> 4247</div> 4248</div> 4249<div class="dlist"> 4250<dl> 4251<dt class="hdlist1">Returns: </dt> 4252<dd> 4253<p>The squared magnitude of the vector <code>a</code>.</p> 4254</dd> 4255</dl> 4256</div> 4257<hr> 4258</div> 4259<div class="sect3"> 4260<h4 id="vec_mag"><code>mag</code></h4> 4261<div class="listingblock"> 4262<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4263<div class="content"> 4264<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4265 4266 //Only enabled if: 4267 // is_vec<A>::value 4268 template <class A> 4269 typename vec_traits<A>::scalar_type 4270 mag( A const & a ); 4271 4272} }</code></pre> 4273</div> 4274</div> 4275<div class="dlist"> 4276<dl> 4277<dt class="hdlist1">Returns: </dt> 4278<dd> 4279<p>The magnitude of the vector <code>a</code>.</p> 4280</dd> 4281</dl> 4282</div> 4283<hr> 4284</div> 4285<div class="sect3"> 4286<h4 id="vec_normalized"><code>normalized</code></h4> 4287<div class="listingblock"> 4288<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4289<div class="content"> 4290<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4291 4292 //Only enabled if: 4293 // is_vec<A>::value 4294 template <class A> 4295 typename deduce_vec<A>::type 4296 normalized( A const & a ); 4297 4298} }</code></pre> 4299</div> 4300</div> 4301<div class="dlist"> 4302<dl> 4303<dt class="hdlist1">Effects: </dt> 4304<dd> 4305<p>As if:</p> 4306<div class="listingblock"> 4307<div class="content"> 4308<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">typename deduce_vec<A>::type tmp; 4309assign(tmp,a); 4310normalize(tmp); 4311return tmp;</code></pre> 4312</div> 4313</div> 4314</dd> 4315</dl> 4316</div> 4317<div class="admonitionblock note"> 4318<table> 4319<tr> 4320<td class="icon"> 4321<i class="fa icon-note" title="Note"></i> 4322</td> 4323<td class="content"> 4324The <a href="#deduce_vec"><code>deduce_vec</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 4325</td> 4326</tr> 4327</table> 4328</div> 4329<hr> 4330</div> 4331<div class="sect3"> 4332<h4 id="vec_normalize"><code>normalize</code></h4> 4333<div class="listingblock"> 4334<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4335<div class="content"> 4336<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4337 4338 //Only enabled if: 4339 // is_vec<A>::value 4340 template <class A> 4341 void normalize( A & a ); 4342 4343} }</code></pre> 4344</div> 4345</div> 4346<div class="dlist"> 4347<dl> 4348<dt class="hdlist1">Effects: </dt> 4349<dd> 4350<p>Normalizes <code>a</code>.</p> 4351</dd> 4352</dl> 4353</div> 4354<div class="paragraph"> 4355<p>Ensures:</p> 4356</div> 4357<div class="paragraph"> 4358<p><code>mag(a)==<a href="#scalar_traits">scalar_traits</a><typename <a href="#vec_traits">vec_traits<A>::scalar_type</a>>::value(1)</code>.</p> 4359</div> 4360<div class="dlist"> 4361<dl> 4362<dt class="hdlist1">Throws: </dt> 4363<dd> 4364<p>If the magnitude of <code>a</code> is zero, throws <a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a>.</p> 4365</dd> 4366</dl> 4367</div> 4368<hr> 4369</div> 4370<div class="sect3"> 4371<h4 id="vec_dot"><code>dot</code></h4> 4372<div class="listingblock"> 4373<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4374<div class="content"> 4375<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4376 4377 //Only enabled if: 4378 // is_vec<A>::value && is_vec<B>::value && 4379 // vec_traits<A>::dim==vec_traits<B>::dim 4380 template <class A,class B> 4381 typename deduce_scalar<A,B>::type 4382 dot( A const & a, B const & b ); 4383 4384} }</code></pre> 4385</div> 4386</div> 4387<div class="dlist"> 4388<dl> 4389<dt class="hdlist1">Returns: </dt> 4390<dd> 4391<p>The dot product of the vectors <code>a</code> and <code>b</code>.</p> 4392</dd> 4393</dl> 4394</div> 4395<div class="admonitionblock note"> 4396<table> 4397<tr> 4398<td class="icon"> 4399<i class="fa icon-note" title="Note"></i> 4400</td> 4401<td class="content"> 4402The <a href="#deduce_scalar"><code>deduce_scalar</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4403</td> 4404</tr> 4405</table> 4406</div> 4407<hr> 4408</div> 4409<div class="sect3"> 4410<h4 id="vec_cross"><code>cross</code></h4> 4411<div class="listingblock"> 4412<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4413<div class="content"> 4414<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4415 4416 //Only enabled if: 4417 // is_vec<A>::value && is_vec<B>::value && 4418 // vec_traits<A>::dim==3 && vec_traits<B>::dim==3 4419 template <class A,class B> 4420 typename deduce_vec2<A,B,3>::type 4421 cross( A const & a, B const & b ); 4422 4423} }</code></pre> 4424</div> 4425</div> 4426<div class="dlist"> 4427<dl> 4428<dt class="hdlist1">Returns: </dt> 4429<dd> 4430<p>The cross product of the vectors <code>a</code> and <code>b</code>.</p> 4431</dd> 4432</dl> 4433</div> 4434<div class="admonitionblock note"> 4435<table> 4436<tr> 4437<td class="icon"> 4438<i class="fa icon-note" title="Note"></i> 4439</td> 4440<td class="content"> 4441The <a href="#deduce_vec2"><code>deduce_vec2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4442</td> 4443</tr> 4444</table> 4445</div> 4446<hr> 4447</div> 4448<div class="sect3"> 4449<h4 id="zero_vec"><code>zero_vec</code></h4> 4450<div class="listingblock"> 4451<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4452<div class="content"> 4453<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4454 4455 template <class T,int S> 4456 -unspecified-return-type- zero_vec(); 4457 4458} }</code></pre> 4459</div> 4460</div> 4461<div class="dlist"> 4462<dl> 4463<dt class="hdlist1">Returns: </dt> 4464<dd> 4465<p>A read-only vector of unspecified type with <a href="#vec_traits"><code>scalar_type</code></a> <code>T</code> and size <code>S</code>, with all elements equal to <a href="#scalar_traits"><code>scalar_traits<T>::value(0)</code></a>.</p> 4466</dd> 4467</dl> 4468</div> 4469<hr> 4470</div> 4471<div class="sect3"> 4472<h4 id="vec_set_zero"><code>set_zero</code></h4> 4473<div class="listingblock"> 4474<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4475<div class="content"> 4476<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4477 4478 //Only enabled if: 4479 // is_vec<A>::value 4480 template <class A> 4481 void set_zero( A & a ); 4482 4483} }</code></pre> 4484</div> 4485</div> 4486<div class="dlist"> 4487<dl> 4488<dt class="hdlist1">Effects: </dt> 4489<dd> 4490<p>As if:</p> 4491<div class="listingblock"> 4492<div class="content"> 4493<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign(a, 4494 zero_vec< 4495 typename vec_traits<A>::scalar_type, 4496 vec_traits<A>::dim>());</code></pre> 4497</div> 4498</div> 4499</dd> 4500</dl> 4501</div> 4502<hr> 4503</div> 4504<div class="sect3"> 4505<h4 id="vec_scalar_cast"><code>scalar_cast</code></h4> 4506<div class="listingblock"> 4507<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4508<div class="content"> 4509<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4510 4511 //Only enabled if: is_vec<A>::value 4512 template <class Scalar,class A> 4513 -unspecified-return_type- scalar_cast( A const & a ); 4514 4515} }</code></pre> 4516</div> 4517</div> 4518<div class="dlist"> 4519<dl> 4520<dt class="hdlist1">Returns: </dt> 4521<dd> 4522<p>A read-only <a href="#view_proxy">view proxy</a> of <code>a</code> that looks like a vector of the same dimensions as <code>a</code>, but with <a href="#vec_traits"><code>scalar_type</code></a> <code>Scalar</code> and elements constructed from the corresponding elements of <code>a</code>.</p> 4523</dd> 4524</dl> 4525</div> 4526<hr> 4527</div> 4528<div class="sect3"> 4529<h4 id="vref"><code>vref</code></h4> 4530<div class="listingblock"> 4531<div class="title">#include <boost/qvm/vec_operations.hpp></div> 4532<div class="content"> 4533<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4534 4535 //Only enabled if: is_vec<A>::value 4536 template <class A> 4537 -unspecified-return-type- vref( A & a ); 4538 4539} }</code></pre> 4540</div> 4541</div> 4542<div class="dlist"> 4543<dl> 4544<dt class="hdlist1">Returns: </dt> 4545<dd> 4546<p>An identity <a href="#view_proxy">view proxy</a> of <code>a</code>; that is, it simply accesses the elements of <code>a</code>.</p> 4547</dd> 4548</dl> 4549</div> 4550<div class="admonitionblock tip"> 4551<table> 4552<tr> 4553<td class="icon"> 4554<i class="fa icon-tip" title="Tip"></i> 4555</td> 4556<td class="content"> 4557<code>vref</code> allows calling QVM operations when <code>a</code> is of built-in type, for example a plain old C array. 4558</td> 4559</tr> 4560</table> 4561</div> 4562<hr> 4563</div> 4564</div> 4565<div class="sect2"> 4566<h3 id="_matrix_operations">Matrix Operations</h3> 4567<div class="sect3"> 4568<h4 id="mat_assign"><code>assign</code></h4> 4569<div class="listingblock"> 4570<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4571<div class="content"> 4572<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4573 4574 //Only enabled if: 4575 // is_mat<A>::value && is_mat<B>::value && 4576 // mat_traits<A>::rows==mat_traits<B>::rows && 4577 // mat_traits<A>::cols==mat_traits<B>::cols 4578 template <class A,class B> 4579 A & assign( A & a, B const & b ); 4580 4581} }</code></pre> 4582</div> 4583</div> 4584<div class="dlist"> 4585<dl> 4586<dt class="hdlist1">Effects: </dt> 4587<dd> 4588<p>Copies all elements of the matrix <code>b</code> to the matrix <code>a</code>.</p> 4589</dd> 4590<dt class="hdlist1">Returns: </dt> 4591<dd> 4592<p><code>a</code>.</p> 4593</dd> 4594</dl> 4595</div> 4596<hr> 4597</div> 4598<div class="sect3"> 4599<h4 id="mat_convert_to"><code>convert_to</code></h4> 4600<div class="listingblock"> 4601<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4602<div class="content"> 4603<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4604 4605 //Only enabled if: 4606 // is_mat<R>::value && is_mat<A>::value && 4607 // mat_traits<R>::rows==mat_traits<A>::rows && 4608 // mat_traits<R>::cols==mat_traits<A>::cols 4609 template <class R,class A> 4610 R convert_to( A const & a ); 4611 4612} }</code></pre> 4613</div> 4614</div> 4615<div class="dlist"> 4616<dl> 4617<dt class="hdlist1">Requires: </dt> 4618<dd> 4619<p><code>R</code> must be copyable.</p> 4620</dd> 4621</dl> 4622</div> 4623<div class="paragraph"> 4624<p>Effects:</p> 4625</div> 4626<div class="paragraph"> 4627<p>As if: <code>R r; <a href="#mat_assign">assign</a>(r,a); return r;</code></p> 4628</div> 4629<hr> 4630</div> 4631<div class="sect3"> 4632<h4 id="mat_minus_eq_scalar"><code>operator-=</code></h4> 4633<div class="listingblock"> 4634<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4635<div class="content"> 4636<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4637 4638 //Only enabled if: 4639 // is_mat<A>::value && is_mat<B>::value && 4640 // mat_traits<A>::rows==mat_traits<B>::rows && 4641 // mat_traits<A>::cols==mat_traits<B>::cols 4642 template <class A,class B> 4643 A & operator-=( A & a, B const & b ); 4644 4645} }</code></pre> 4646</div> 4647</div> 4648<div class="dlist"> 4649<dl> 4650<dt class="hdlist1">Effects: </dt> 4651<dd> 4652<p>Subtracts the elements of <code>b</code> from the corresponding elements of <code>a</code>.</p> 4653</dd> 4654<dt class="hdlist1">Returns: </dt> 4655<dd> 4656<p><code>a</code>.</p> 4657</dd> 4658</dl> 4659</div> 4660<hr> 4661</div> 4662<div class="sect3"> 4663<h4 id="mat_minus_unary"><code>operator-</code> (unary)</h4> 4664<div class="listingblock"> 4665<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4666<div class="content"> 4667<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4668 4669 //Only enabled if: is_mat<A>::value 4670 template <class A> 4671 typename deduce_mat<A>::type 4672 operator-( A const & a ); 4673 4674} }</code></pre> 4675</div> 4676</div> 4677<div class="dlist"> 4678<dl> 4679<dt class="hdlist1">Returns: </dt> 4680<dd> 4681<p>A matrix of the negated elements of <code>a</code>.</p> 4682</dd> 4683</dl> 4684</div> 4685<div class="admonitionblock note"> 4686<table> 4687<tr> 4688<td class="icon"> 4689<i class="fa icon-note" title="Note"></i> 4690</td> 4691<td class="content"> 4692The <a href="#deduce_mat"><code>deduce_mat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 4693</td> 4694</tr> 4695</table> 4696</div> 4697<hr> 4698</div> 4699<div class="sect3"> 4700<h4 id="mat_minus"><code>operator-</code></h4> 4701<div class="listingblock"> 4702<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4703<div class="content"> 4704<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4705 4706 //Only enabled if: 4707 // is_mat<A>::value && is_mat<B>::value && 4708 // mat_traits<A>::rows==mat_traits<B>::rows && 4709 // mat_traits<A>::cols==mat_traits<B>::cols 4710 template <class A,class B> 4711 typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type 4712 operator-( A const & a, B const & b ); 4713 4714} }</code></pre> 4715</div> 4716</div> 4717<div class="dlist"> 4718<dl> 4719<dt class="hdlist1">Returns: </dt> 4720<dd> 4721<p>A matrix of the same size as <code>a</code> and <code>b</code>, with elements the elements of <code>b</code> subtracted from the corresponding elements of <code>a</code>.</p> 4722</dd> 4723</dl> 4724</div> 4725<div class="admonitionblock note"> 4726<table> 4727<tr> 4728<td class="icon"> 4729<i class="fa icon-note" title="Note"></i> 4730</td> 4731<td class="content"> 4732The <a href="#deduce_mat2"><code>deduce_mat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4733</td> 4734</tr> 4735</table> 4736</div> 4737<hr> 4738</div> 4739<div class="sect3"> 4740<h4 id="mat_plus_eq_scalar"><code>operator+=</code></h4> 4741<div class="listingblock"> 4742<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4743<div class="content"> 4744<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4745 4746 //Only enabled if: 4747 // is_mat<A>::value && is_mat<B>::value && 4748 // mat_traits<A>::rows==mat_traits<B>::rows && 4749 // mat_traits<A>::cols==mat_traits<B>::cols 4750 template <class A,class B> 4751 A & operator+=( A & a, B const & b ); 4752 4753} }</code></pre> 4754</div> 4755</div> 4756<div class="dlist"> 4757<dl> 4758<dt class="hdlist1">Effects: </dt> 4759<dd> 4760<p>Adds the elements of <code>b</code> to the corresponding elements of <code>a</code>.</p> 4761</dd> 4762<dt class="hdlist1">Returns: </dt> 4763<dd> 4764<p><code>a</code>.</p> 4765</dd> 4766</dl> 4767</div> 4768<hr> 4769</div> 4770<div class="sect3"> 4771<h4 id="mat_plus"><code>operator+</code></h4> 4772<div class="listingblock"> 4773<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4774<div class="content"> 4775<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4776 4777 //Only enabled if: 4778 // is_mat<A>::value && is_mat<B>::value && 4779 // mat_traits<A>::rows==mat_traits<B>::rows && 4780 // mat_traits<A>::cols==mat_traits<B>::cols 4781 template <class A,class B> 4782 typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type 4783 operator+( A const & a, B const & b ); 4784 4785} }</code></pre> 4786</div> 4787</div> 4788<div class="dlist"> 4789<dl> 4790<dt class="hdlist1">Returns: </dt> 4791<dd> 4792<p>A matrix of the same size as <code>a</code> and <code>b</code>, with elements the elements of <code>b</code> added to the corresponding elements of <code>a</code>.</p> 4793</dd> 4794</dl> 4795</div> 4796<div class="admonitionblock note"> 4797<table> 4798<tr> 4799<td class="icon"> 4800<i class="fa icon-note" title="Note"></i> 4801</td> 4802<td class="content"> 4803The <a href="#deduce_mat2"><code>deduce_mat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4804</td> 4805</tr> 4806</table> 4807</div> 4808<hr> 4809</div> 4810<div class="sect3"> 4811<h4 id="mat_div_eq_scalar"><code>operator/=</code> (scalar)</h4> 4812<div class="listingblock"> 4813<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4814<div class="content"> 4815<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4816 4817 //Only enabled if: is_mat<A>::value && is_scalar<B>::value 4818 template <class A,class B> 4819 A & operator/=( A & a, B b ); 4820 4821} }</code></pre> 4822</div> 4823</div> 4824<div class="dlist"> 4825<dl> 4826<dt class="hdlist1">Effects: </dt> 4827<dd> 4828<p>This operation divides a matrix by a scalar.</p> 4829</dd> 4830<dt class="hdlist1">Returns: </dt> 4831<dd> 4832<p><code>a</code>.</p> 4833</dd> 4834</dl> 4835</div> 4836<hr> 4837</div> 4838<div class="sect3"> 4839<h4 id="mat_div_scalar"><code>operator/</code> (scalar)</h4> 4840<div class="listingblock"> 4841<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4842<div class="content"> 4843<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4844 4845 //Only enabled if: is_mat<A>::value && is_scalar<B>::value 4846 template <class A,class B> 4847 typename deduce_mat<A>::type 4848 operator/( A const & a, B b ); 4849 4850} }</code></pre> 4851</div> 4852</div> 4853<div class="dlist"> 4854<dl> 4855<dt class="hdlist1">Returns: </dt> 4856<dd> 4857<p>A matrix that is the result of dividing the matrix <code>a</code> by the scalar <code>b</code>.</p> 4858</dd> 4859</dl> 4860</div> 4861<div class="admonitionblock note"> 4862<table> 4863<tr> 4864<td class="icon"> 4865<i class="fa icon-note" title="Note"></i> 4866</td> 4867<td class="content"> 4868The <a href="#deduce_mat"><code>deduce_mat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 4869</td> 4870</tr> 4871</table> 4872</div> 4873<hr> 4874</div> 4875<div class="sect3"> 4876<h4 id="mat_mul_eq"><code>operator*=</code></h4> 4877<div class="listingblock"> 4878<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4879<div class="content"> 4880<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4881 4882 //Only enabled if: 4883 // is_mat<A>::value && is_mat<B>::value && 4884 // mat_traits<A>::rows==mat_traits<A>::cols && 4885 // mat_traits<A>::rows==mat_traits<B>::rows && 4886 // mat_traits<A>::cols==mat_traits<B>::cols 4887 template <class A,class B> 4888 A & operator*=( A & a, B const & b ); 4889 4890} }</code></pre> 4891</div> 4892</div> 4893<div class="dlist"> 4894<dl> 4895<dt class="hdlist1">Effects: </dt> 4896<dd> 4897<p>As if:</p> 4898<div class="listingblock"> 4899<div class="content"> 4900<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">A tmp(a); 4901a = tmp * b; 4902return a;</code></pre> 4903</div> 4904</div> 4905</dd> 4906</dl> 4907</div> 4908<hr> 4909</div> 4910<div class="sect3"> 4911<h4 id="mat_mul_eq_scalar"><code>operator*=</code> (scalar)</h4> 4912<div class="listingblock"> 4913<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4914<div class="content"> 4915<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4916 4917 //Only enabled if: is_mat<A>::value && is_scalar<B>::value 4918 template <class A,class B> 4919 A & operator*=( A & a, B b ); 4920 4921} }</code></pre> 4922</div> 4923</div> 4924<div class="dlist"> 4925<dl> 4926<dt class="hdlist1">Effects: </dt> 4927<dd> 4928<p>This operation multiplies the matrix <code>a</code> matrix by the scalar <code>b</code>.</p> 4929</dd> 4930<dt class="hdlist1">Returns: </dt> 4931<dd> 4932<p><code>a</code>.</p> 4933</dd> 4934</dl> 4935</div> 4936<hr> 4937</div> 4938<div class="sect3"> 4939<h4 id="mat_mul"><code>operator*</code></h4> 4940<div class="listingblock"> 4941<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4942<div class="content"> 4943<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4944 4945 //Only enabled if: 4946 // is_mat<A>::value && is_mat<B>::value && 4947 // mat_traits<A>::cols==mat_traits<B>::rows 4948 template <class A,class B> 4949 typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<B>::cols>::type 4950 operator*( A const & a, B const & b ); 4951 4952} }</code></pre> 4953</div> 4954</div> 4955<div class="dlist"> 4956<dl> 4957<dt class="hdlist1">Returns: </dt> 4958<dd> 4959<p>The result of <a href="https://en.wikipedia.org/wiki/Matrix_multiplication">multiplying</a> the matrices <code>a</code> and <code>b</code>.</p> 4960</dd> 4961</dl> 4962</div> 4963<div class="admonitionblock note"> 4964<table> 4965<tr> 4966<td class="icon"> 4967<i class="fa icon-note" title="Note"></i> 4968</td> 4969<td class="content"> 4970The <a href="#deduce_mat2"><code>deduce_mat2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 4971</td> 4972</tr> 4973</table> 4974</div> 4975<hr> 4976</div> 4977<div class="sect3"> 4978<h4 id="mat_mul_scalar"><code>operator*</code> (scalar)</h4> 4979<div class="listingblock"> 4980<div class="title">#include <boost/qvm/mat_operations.hpp></div> 4981<div class="content"> 4982<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 4983 4984 //Only enabled if: is_mat<A>::value && is_scalar<B>::value 4985 template <class A,class B> 4986 typename deduce_mat<A>::type 4987 operator*( A const & a, B b ); 4988 4989 //Only enabled if: is_scalar<B>::value && is_mat<A>::value 4990 template <class B,class A> 4991 typename deduce_mat<A>::type 4992 operator*( B b, A const & a ); 4993 4994} }</code></pre> 4995</div> 4996</div> 4997<div class="dlist"> 4998<dl> 4999<dt class="hdlist1">Returns: </dt> 5000<dd> 5001<p>A matrix that is the result of multiplying the matrix <code>a</code> by the scalar <code>b</code>.</p> 5002</dd> 5003</dl> 5004</div> 5005<div class="admonitionblock note"> 5006<table> 5007<tr> 5008<td class="icon"> 5009<i class="fa icon-note" title="Note"></i> 5010</td> 5011<td class="content"> 5012The <a href="#deduce_mat"><code>deduce_mat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 5013</td> 5014</tr> 5015</table> 5016</div> 5017<hr> 5018</div> 5019<div class="sect3"> 5020<h4 id="mat_eq"><code>operator==</code></h4> 5021<div class="listingblock"> 5022<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5023<div class="content"> 5024<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5025 5026 //Only enabled if: 5027 // is_mat<A>::value && is_mat<B>::value && 5028 // mat_traits<A>::rows==mat_traits<B>::rows && 5029 // mat_traits<A>::cols==mat_traits<B>::cols 5030 template <class A,class B> 5031 bool operator==( A const & a, B const & b ); 5032 5033} }</code></pre> 5034</div> 5035</div> 5036<div class="dlist"> 5037<dl> 5038<dt class="hdlist1">Returns: </dt> 5039<dd> 5040<p><code>true</code> if each element of <code>a</code> compares equal to its corresponding element of <code>b</code>, <code>false</code> otherwise.</p> 5041</dd> 5042</dl> 5043</div> 5044<hr> 5045</div> 5046<div class="sect3"> 5047<h4 id="mat_neq"><code>operator!=</code></h4> 5048<div class="listingblock"> 5049<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5050<div class="content"> 5051<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5052 5053 //Only enabled if: 5054 // is_mat<A>::value && is_mat<B>::value && 5055 // mat_traits<A>::rows==mat_traits<B>::rows && 5056 // mat_traits<A>::cols==mat_traits<B>::cols 5057 template <class A,class B> 5058 bool operator!=( A const & a, B const & b ); 5059 5060} }</code></pre> 5061</div> 5062</div> 5063<div class="dlist"> 5064<dl> 5065<dt class="hdlist1">Returns: </dt> 5066<dd> 5067<p><code>!( a <a href="#mat_eq">==</a> b )</code>.</p> 5068</dd> 5069</dl> 5070</div> 5071<hr> 5072</div> 5073<div class="sect3"> 5074<h4 id="mat_cmp"><code>cmp</code></h4> 5075<div class="listingblock"> 5076<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5077<div class="content"> 5078<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5079 5080 //Only enabled if: 5081 // is_mat<A>::value && is_mat<B>::value && 5082 // mat_traits<A>::rows==mat_traits<B>::rows && 5083 // mat_traits<A>::cols==mat_traits<B>::cols 5084 template <class A,class B,class Cmp> 5085 bool cmp( A const & a, B const & b, Cmp pred ); 5086 5087} }</code></pre> 5088</div> 5089</div> 5090<div class="dlist"> 5091<dl> 5092<dt class="hdlist1">Returns: </dt> 5093<dd> 5094<p>Similar to <a href="#mat_eq"><code>operator==</code></a>, except that the individual elements of <code>a</code> and <code>b</code> are passed to the binary predicate <code>pred</code> for comparison.</p> 5095</dd> 5096</dl> 5097</div> 5098<hr> 5099</div> 5100<div class="sect3"> 5101<h4 id="mat_inverse"><code>inverse</code></h4> 5102<div class="listingblock"> 5103<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5104<div class="content"> 5105<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5106 5107 //Only enabled if: 5108 // is_mat<A>::value && is_scalar<B>::value 5109 // mat_traits<A>::rows==mat_traits<A>::cols 5110 5111 template <class A,class B> 5112 typename deduce_mat<A>::type 5113 inverse( A const & a, B det ); 5114 5115 template <class A> 5116 typename deduce_mat<A>::type 5117 inverse( A const & a ); 5118 5119} }</code></pre> 5120</div> 5121</div> 5122<div class="dlist"> 5123<dl> 5124<dt class="hdlist1">Preconditions: </dt> 5125<dd> 5126<p><code>det!=<a href="#scalar_traits">scalar_traits</a><typename <a href="#mat_traits">mat_traits<A>::scalar_type</a>>::value(0)</code></p> 5127</dd> 5128<dt class="hdlist1">Returns: </dt> 5129<dd> 5130<p>Both overloads compute the inverse of <code>a</code>. The first overload takes the pre-computed determinant of <code>a</code>.</p> 5131</dd> 5132<dt class="hdlist1">Throws: </dt> 5133<dd> 5134<p>The second overload computes the determinant automatically and throws <a href="#zero_determinant_error"><code>zero_determinant_error</code></a> if the computed determinant is zero.</p> 5135</dd> 5136</dl> 5137</div> 5138<div class="admonitionblock note"> 5139<table> 5140<tr> 5141<td class="icon"> 5142<i class="fa icon-note" title="Note"></i> 5143</td> 5144<td class="content"> 5145The <a href="#deduce_mat"><code>deduce_mat</code></a> template can be specialized to deduce the desired return type from the type <code>A</code>. 5146</td> 5147</tr> 5148</table> 5149</div> 5150<hr> 5151</div> 5152<div class="sect3"> 5153<h4 id="zero_mat"><code>zero_mat</code></h4> 5154<div class="listingblock"> 5155<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5156<div class="content"> 5157<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5158 5159 template <class T,int D> 5160 -unspecified-return-type- zero_mat(); 5161 5162 template <class T,int R,int C> 5163 -unspecified-return-type- zero_mat(); 5164 5165} }</code></pre> 5166</div> 5167</div> 5168<div class="dlist"> 5169<dl> 5170<dt class="hdlist1">Returns: </dt> 5171<dd> 5172<p>A read-only matrix of unspecified type with <a href="#mat_traits"><code>scalar_type</code></a> <code>T</code>, <code>R</code> rows and <code>C</code> columns (or <code>D</code> rows and <code>D</code> columns), with all elements equal to <a href="#scalar_traits"><code>scalar_traits<T>::value(0)</code></a>.</p> 5173</dd> 5174</dl> 5175</div> 5176<hr> 5177</div> 5178<div class="sect3"> 5179<h4 id="mat_set_zero"><code>set_zero</code></h4> 5180<div class="listingblock"> 5181<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5182<div class="content"> 5183<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5184 5185 //Only enabled if: 5186 // is_mat<A>::value 5187 template <class A> 5188 void set_zero( A & a ); 5189 5190} }</code></pre> 5191</div> 5192</div> 5193<div class="dlist"> 5194<dl> 5195<dt class="hdlist1">Effects: </dt> 5196<dd> 5197<p>As if:</p> 5198<div class="listingblock"> 5199<div class="content"> 5200<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign(a, 5201 zero_mat< 5202 typename mat_traits<A>::scalar_type, 5203 mat_traits<A>::rows, 5204 mat_traits<A>::cols>());</code></pre> 5205</div> 5206</div> 5207</dd> 5208</dl> 5209</div> 5210<hr> 5211</div> 5212<div class="sect3"> 5213<h4 id="identity_mat"><code>identity_mat</code></h4> 5214<div class="listingblock"> 5215<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5216<div class="content"> 5217<pre class="nowrap">namespace boost { namespace qvm { 5218 5219 template <class S,int D> 5220 -unspecified-return-type- identity_mat(); 5221 5222} }</pre> 5223</div> 5224</div> 5225<div class="dlist"> 5226<dl> 5227<dt class="hdlist1">Returns: </dt> 5228<dd> 5229<p>An identity matrix of size <code>D</code> x <code>D</code> and scalar type <code>S</code>.</p> 5230</dd> 5231</dl> 5232</div> 5233<hr> 5234</div> 5235<div class="sect3"> 5236<h4 id="mat_set_identity"><code>set_identity</code></h4> 5237<div class="listingblock"> 5238<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5239<div class="content"> 5240<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5241 5242 //Only enabled if: 5243 // is_mat<A>::value && 5244 // mat_traits<A>::cols==mat_traits<A>::rows 5245 template <class A> 5246 void set_identity( A & a ); 5247 5248} }</code></pre> 5249</div> 5250</div> 5251<div class="dlist"> 5252<dl> 5253<dt class="hdlist1">Effects: </dt> 5254<dd> 5255<p>As if:</p> 5256<div class="listingblock"> 5257<div class="content"> 5258<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 5259 a, 5260 identity_mat< 5261 typename mat_traits<A>::scalar_type, 5262 mat_traits<A>::rows, 5263 mat_traits<A>::cols>());</code></pre> 5264</div> 5265</div> 5266</dd> 5267</dl> 5268</div> 5269<hr> 5270</div> 5271<div class="sect3"> 5272<h4 id="rot_mat"><code>rot_mat</code> / Euler angles</h4> 5273<div class="listingblock"> 5274<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5275<div class="content"> 5276<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5277 5278 //Only enabled if: 5279 // is_vec<A>::value && vec_traits<A>::dim==3 5280 template <int Dim,class A,class Angle> 5281 -unspecified-return-type- 5282 rot_mat( A const & axis, Angle angle ); 5283 5284 template <int Dim,class Angle> 5285 -unspecified-return-type- 5286 rot_mat_xzy( Angle x1, Angle z2, Angle y3 ); 5287 5288 template <int Dim,class Angle> 5289 -unspecified-return-type- 5290 rot_mat_xyz( Angle x1, Angle y2, Angle z3 ); 5291 5292 template <int Dim,class Angle> 5293 -unspecified-return-type- 5294 rot_mat_yxz( Angle y1, Angle x2, Angle z3 ); 5295 5296 template <int Dim,class Angle> 5297 -unspecified-return-type- 5298 rot_mat_yzx( Angle y1, Angle z2, Angle x3 ); 5299 5300 template <int Dim,class Angle> 5301 -unspecified-return-type- 5302 rot_mat_zyx( Angle z1, Angle y2, Angle x3 ); 5303 5304 template <int Dim,class Angle> 5305 -unspecified-return-type- 5306 rot_mat_zxy( Angle z1, Angle x2, Angle y3 ); 5307 5308 template <int Dim,class Angle> 5309 -unspecified-return-type- 5310 rot_mat_xzx( Angle x1, Angle z2, Angle x3 ); 5311 5312 template <int Dim,class Angle> 5313 -unspecified-return-type- 5314 rot_mat_xyx( Angle x1, Angle y2, Angle x3 ); 5315 5316 template <int Dim,class Angle> 5317 -unspecified-return-type- 5318 rot_mat_yxy( Angle y1, Angle x2, Angle y3 ); 5319 5320 template <int Dim,class Angle> 5321 -unspecified-return-type- 5322 rot_mat_yzy( Angle y1, Angle z2, Angle y3 ); 5323 5324 template <int Dim,class Angle> 5325 -unspecified-return-type- 5326 rot_mat_zyz( Angle z1, Angle y2, Angle z3 ); 5327 5328 template <int Dim,class Angle> 5329 -unspecified-return-type- 5330 rot_mat_zxz( Angle z1, Angle y2, Angle z3 ); 5331 5332} }</code></pre> 5333</div> 5334</div> 5335<div class="dlist"> 5336<dl> 5337<dt class="hdlist1">Returns: </dt> 5338<dd> 5339<p>A matrix of unspecified type, of <code>Dim</code> rows and <code>Dim</code> columns parameter, which performs a rotation around the <code>axis</code> at <code>angle</code> 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 <a href="https://en.wikipedia.org/wiki/Euler_angles">Euler angles</a>.</p> 5340</dd> 5341<dt class="hdlist1">Throws: </dt> 5342<dd> 5343<p>In case the axis vector has zero magnitude, throws <a href="#zero_magnitude_error"><code>zero_magnitude_error</code></a>.</p> 5344</dd> 5345</dl> 5346</div> 5347<div class="admonitionblock note"> 5348<table> 5349<tr> 5350<td class="icon"> 5351<i class="fa icon-note" title="Note"></i> 5352</td> 5353<td class="content"> 5354These functions are not view proxies; they return a temp object. 5355</td> 5356</tr> 5357</table> 5358</div> 5359<hr> 5360</div> 5361<div class="sect3"> 5362<h4 id="mat_set_rot"><code>set_rot</code> / Euler angles</h4> 5363<div class="listingblock"> 5364<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5365<div class="content"> 5366<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5367 5368 //Only enabled if: 5369 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5370 // mat_traits<A>::rows==mat_traits<A>::cols && 5371 // is_vec<B>::value && vec_traits<B>::dim==3 5372 template <class A> 5373 void set_rot( A & a, B const & axis, typename vec_traits<B>::scalar_type angle ); 5374 5375 //Only enabled if: 5376 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5377 // mat_traits<A>::rows==mat_traits<A>::cols 5378 template <class A,class Angle> 5379 void set_rot_xzy( A & a, Angle x1, Angle z2, Angle y3 ); 5380 5381 //Only enabled if: 5382 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5383 // mat_traits<A>::rows==mat_traits<A>::cols 5384 template <class A,class Angle> 5385 void set_rot_xyz( A & a, Angle x1, Angle y2, Angle z3 ); 5386 5387 //Only enabled if: 5388 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5389 // mat_traits<A>::rows==mat_traits<A>::cols 5390 template <class A,class Angle> 5391 void set_rot_yxz( A & a, Angle y1, Angle x2, Angle z3 ); 5392 5393 //Only enabled if: 5394 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5395 // mat_traits<A>::rows==mat_traits<A>::cols 5396 template <class A,class Angle> 5397 void set_rot_yzx( A & a, Angle y1, Angle z2, Angle x3 ); 5398 5399 //Only enabled if: 5400 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5401 // mat_traits<A>::rows==mat_traits<A>::cols 5402 template <class A,class Angle> 5403 void set_rot_zyx( A & a, Angle z1, Angle y2, Angle x3 ); 5404 5405 //Only enabled if: 5406 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5407 // mat_traits<A>::rows==mat_traits<A>::cols 5408 template <class A,class Angle> 5409 void set_rot_zxy( A & a, Angle z1, Angle x2, Angle y3 ); 5410 5411 //Only enabled if: 5412 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5413 // mat_traits<A>::rows==mat_traits<A>::cols 5414 template <class A,class Angle> 5415 void set_rot_xzx( A & a, Angle x1, Angle z2, Angle x3 ); 5416 5417 //Only enabled if: 5418 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5419 // mat_traits<A>::rows==mat_traits<A>::cols 5420 template <class A,class Angle> 5421 void set_rot_xyx( A & a, Angle x1, Angle y2, Angle x3 ); 5422 5423 //Only enabled if: 5424 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5425 // mat_traits<A>::rows==mat_traits<A>::cols 5426 template <class A,class Angle> 5427 void set_rot_yxy( A & a, Angle y1, Angle x2, Angle y3 ); 5428 5429 //Only enabled if: 5430 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5431 // mat_traits<A>::rows==mat_traits<A>::cols 5432 template <class A,class Angle> 5433 void set_rot_yzy( A & a, Angle y1, Angle z2, Angle y3 ); 5434 5435 //Only enabled if: 5436 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5437 // mat_traits<A>::rows==mat_traits<A>::cols 5438 template <class A,class Angle> 5439 void set_rot_zyz( A & a, Angle z1, Angle y2, Angle z3 ); 5440 5441 //Only enabled if: 5442 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5443 // mat_traits<A>::rows==mat_traits<A>::cols 5444 template <class A,class Angle> 5445 void set_rot_zxz( A & a, Angle z1, Angle x2, Angle z3 ); 5446 5447 //Only enabled if: 5448 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5449 // mat_traits<A>::rows==mat_traits<A>::cols 5450 template <class A,class Angle> 5451 void set_rot_xzy( A & a, Angle x1, Angle z2, Angle y3 ); 5452 5453} }</code></pre> 5454</div> 5455</div> 5456<div class="dlist"> 5457<dl> 5458<dt class="hdlist1">Effects: </dt> 5459<dd> 5460<p>Assigns the return value of the corresponding <a href="#rot_mat"><code>rot_mat</code></a> function to <code>a</code>.</p> 5461</dd> 5462</dl> 5463</div> 5464<hr> 5465</div> 5466<div class="sect3"> 5467<h4 id="mat_rotate"><code>rotate</code> / Euler angles</h4> 5468<div class="listingblock"> 5469<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5470<div class="content"> 5471<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5472 5473 //Only enabled if: 5474 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5475 // mat_traits<A>::rows==mat_traits<A>::cols && 5476 // is_vec<B>::value && vec_traits<B>::dim==3 5477 template <class A,class B> 5478 void rotate( A & a, B const & axis, typename mat_traits<A>::scalar_type angle ); 5479 5480 //Only enabled if: 5481 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5482 // mat_traits<A>::rows==mat_traits<A>::cols 5483 template <class A,class Angle> 5484 void rotate_xzy( A & a, Angle x1, Angle z2, Angle y3 ); 5485 5486 //Only enabled if: 5487 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5488 // mat_traits<A>::rows==mat_traits<A>::cols 5489 template <class A,class Angle> 5490 void rotate_xyz( A & a, Angle x1, Angle y2, Angle z3 ); 5491 5492 //Only enabled if: 5493 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5494 // mat_traits<A>::rows==mat_traits<A>::cols 5495 template <class A,class Angle> 5496 void rotate_yxz( A & a, Angle y1, Angle x2, Angle z3 ); 5497 5498 //Only enabled if: 5499 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5500 // mat_traits<A>::rows==mat_traits<A>::cols 5501 template <class A,class Angle> 5502 void rotate_yzx( A & a, Angle y1, Angle z2, Angle x3 ); 5503 5504 //Only enabled if: 5505 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5506 // mat_traits<A>::rows==mat_traits<A>::cols 5507 template <class A,class Angle> 5508 void rotate_zyx( A & a, Angle z1, Angle y2, Angle x3 ); 5509 5510 //Only enabled if: 5511 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5512 // mat_traits<A>::rows==mat_traits<A>::cols 5513 template <class A,class Angle> 5514 void rotate_zxy( A & a, Angle z1, Angle x2, Angle y3 ); 5515 5516 //Only enabled if: 5517 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5518 // mat_traits<A>::rows==mat_traits<A>::cols 5519 template <class A,class Angle> 5520 void rotate_xzx( A & a, Angle x1, Angle z2, Angle x3 ); 5521 5522 //Only enabled if: 5523 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5524 // mat_traits<A>::rows==mat_traits<A>::cols 5525 template <class A,class Angle> 5526 void rotate_xyx( A & a, Angle x1, Angle y2, Angle x3 ); 5527 5528 //Only enabled if: 5529 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5530 // mat_traits<A>::rows==mat_traits<A>::cols 5531 template <class A,class Angle> 5532 void rotate_yxy( A & a, Angle y1, Angle x2, Angle y3 ); 5533 5534 //Only enabled if: 5535 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5536 // mat_traits<A>::rows==mat_traits<A>::cols 5537 template <class A,class Angle> 5538 void rotate_yzy( A & a, Angle y1, Angle z2, Angle y3 ); 5539 5540 //Only enabled if: 5541 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5542 // mat_traits<A>::rows==mat_traits<A>::cols 5543 template <class A,class Angle> 5544 void rotate_zyz( A & a, Angle z1, Angle y2, Angle z3 ); 5545 5546 //Only enabled if: 5547 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5548 // mat_traits<A>::rows==mat_traits<A>::cols 5549 template <class A,class Angle> 5550 void rotate_zxz( A & a, Angle z1, Angle x2, Angle z3 ); 5551 5552} }</code></pre> 5553</div> 5554</div> 5555<div class="dlist"> 5556<dl> 5557<dt class="hdlist1">Effects: </dt> 5558<dd> 5559<p>Multiplies the matrix <code>a</code> in-place by the return value of the corresponding <a href="#rot_mat"><code>rot_mat</code></a> function.</p> 5560</dd> 5561</dl> 5562</div> 5563<hr> 5564</div> 5565<div class="sect3"> 5566<h4 id="rotx_mat"><code>rotx_mat</code></h4> 5567<div class="listingblock"> 5568<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5569<div class="content"> 5570<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5571 5572 template <int Dim,class Angle> 5573 -unspecified-return-type- rotx_mat( Angle const & angle ); 5574 5575} }</code></pre> 5576</div> 5577</div> 5578<div class="dlist"> 5579<dl> 5580<dt class="hdlist1">Returns: </dt> 5581<dd> 5582<p>A <a href="#view_proxy">view proxy</a> matrix of unspecified type, of <code>Dim</code> rows and <code>Dim</code> columns and scalar type <code>Angle</code>, which performs a rotation around the <code>X</code> axis at <code>angle</code> radians.</p> 5583</dd> 5584</dl> 5585</div> 5586<hr> 5587</div> 5588<div class="sect3"> 5589<h4 id="mat_set_rotx"><code>set_rotx</code></h4> 5590<div class="listingblock"> 5591<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5592<div class="content"> 5593<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5594 5595 //Only enabled if: 5596 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5597 // mat_traits<A>::rows==mat_traits<A>::cols 5598 template <class A> 5599 void set_rotx( A & a, typename mat_traits<A>::scalar_type angle ); 5600 5601} }</code></pre> 5602</div> 5603</div> 5604<div class="dlist"> 5605<dl> 5606<dt class="hdlist1">Effects: </dt> 5607<dd> 5608<p>As if:</p> 5609<div class="listingblock"> 5610<div class="content"> 5611<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 5612 a, 5613 rotx_mat<mat_traits<A>::rows>(angle));</code></pre> 5614</div> 5615</div> 5616</dd> 5617</dl> 5618</div> 5619<hr> 5620</div> 5621<div class="sect3"> 5622<h4 id="mat_rotate_x"><code>rotate_x</code></h4> 5623<div class="listingblock"> 5624<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5625<div class="content"> 5626<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5627 5628 //Only enabled if: 5629 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5630 // mat_traits<A>::rows==mat_traits<A>::cols 5631 template <class A> 5632 void rotate_x( A & a, typename mat_traits<A>::scalar_type angle ); 5633 5634} }</code></pre> 5635</div> 5636</div> 5637<div class="dlist"> 5638<dl> 5639<dt class="hdlist1">Effects: </dt> 5640<dd> 5641<p>As if: <code>a <a href="#mat_mul_eq">*=</a> <a href="#rotx_mat">rotx_mat</a><<a href="#mat_traits">mat_traits<A>::rows</a>>(angle)</code>.</p> 5642</dd> 5643</dl> 5644</div> 5645<hr> 5646</div> 5647<div class="sect3"> 5648<h4 id="roty_mat"><code>roty_mat</code></h4> 5649<div class="listingblock"> 5650<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5651<div class="content"> 5652<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5653 5654 template <int Dim,class Angle> 5655 -unspecified-return-type- roty_mat( Angle const & angle ); 5656 5657} }</code></pre> 5658</div> 5659</div> 5660<div class="dlist"> 5661<dl> 5662<dt class="hdlist1">Returns: </dt> 5663<dd> 5664<p>A <a href="#view_proxy">view proxy</a> matrix of unspecified type, of <code>Dim</code> rows and <code>Dim</code> columns and scalar type <code>Angle</code>, which performs a rotation around the <code>Y</code> axis at <code>angle</code> radians.</p> 5665</dd> 5666</dl> 5667</div> 5668<hr> 5669</div> 5670<div class="sect3"> 5671<h4 id="mat_set_roty"><code>set_roty</code></h4> 5672<div class="listingblock"> 5673<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5674<div class="content"> 5675<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5676 5677 //Only enabled if: 5678 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5679 // mat_traits<A>::rows==mat_traits<A>::cols 5680 template <class A> 5681 void set_roty( A & a, typename mat_traits<A>::scalar_type angle ); 5682 5683} }</code></pre> 5684</div> 5685</div> 5686<div class="dlist"> 5687<dl> 5688<dt class="hdlist1">Effects: </dt> 5689<dd> 5690<p>As if:</p> 5691<div class="listingblock"> 5692<div class="content"> 5693<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 5694 a, 5695 roty_mat<mat_traits<A>::rows>(angle));</code></pre> 5696</div> 5697</div> 5698</dd> 5699</dl> 5700</div> 5701<hr> 5702</div> 5703<div class="sect3"> 5704<h4 id="mat_rotate_y"><code>rotate_y</code></h4> 5705<div class="listingblock"> 5706<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5707<div class="content"> 5708<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5709 5710 //Only enabled if: 5711 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5712 // mat_traits<A>::rows==mat_traits<A>::cols 5713 template <class A> 5714 void rotate_y( A & a, typename mat_traits<A>::scalar_type angle ); 5715 5716} }</code></pre> 5717</div> 5718</div> 5719<div class="dlist"> 5720<dl> 5721<dt class="hdlist1">Effects: </dt> 5722<dd> 5723<p>As if: <code>a <a href="#mat_mul_eq">*=</a> <a href="#roty_mat">roty_mat</a><<a href="#mat_traits">mat_traits<A>::rows</a>>(angle)</code>.</p> 5724</dd> 5725</dl> 5726</div> 5727<hr> 5728</div> 5729<div class="sect3"> 5730<h4 id="rotz_mat"><code>rotz_mat</code></h4> 5731<div class="listingblock"> 5732<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5733<div class="content"> 5734<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5735 5736 template <int Dim,class Angle> 5737 -unspecified-return-type- rotz_mat( Angle const & angle ); 5738 5739} }</code></pre> 5740</div> 5741</div> 5742<div class="dlist"> 5743<dl> 5744<dt class="hdlist1">Returns: </dt> 5745<dd> 5746<p>A <a href="#view_proxy">view proxy</a> matrix of unspecified type, of <code>Dim</code> rows and <code>Dim</code> columns and scalar type <code>Angle</code>, which performs a rotation around the <code>Z</code> axis at <code>angle</code> radians.</p> 5747</dd> 5748</dl> 5749</div> 5750<hr> 5751</div> 5752<div class="sect3"> 5753<h4 id="mat_set_rotz"><code>set_rotz</code></h4> 5754<div class="listingblock"> 5755<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5756<div class="content"> 5757<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5758 5759 //Only enabled if: 5760 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5761 // mat_traits<A>::rows==mat_traits<A>::cols 5762 template <class A> 5763 void set_rotz( A & a, typename mat_traits<A>::scalar_type angle ); 5764 5765} }</code></pre> 5766</div> 5767</div> 5768<div class="dlist"> 5769<dl> 5770<dt class="hdlist1">Effects: </dt> 5771<dd> 5772<p>As if:</p> 5773<div class="listingblock"> 5774<div class="content"> 5775<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">assign( 5776 a, 5777 rotz_mat<mat_traits<A>::rows>(angle));</code></pre> 5778</div> 5779</div> 5780</dd> 5781</dl> 5782</div> 5783<hr> 5784</div> 5785<div class="sect3"> 5786<h4 id="mat_rotate_z"><code>rotate_z</code></h4> 5787<div class="listingblock"> 5788<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5789<div class="content"> 5790<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5791 5792 //Only enabled if: 5793 // is_mat<A>::value && mat_traits<A>::rows>=3 && 5794 // mat_traits<A>::rows==mat_traits<A>::cols 5795 template <class A> 5796 void rotate_z( A & a, typename mat_traits<A>::scalar_type angle ); 5797 5798} }</code></pre> 5799</div> 5800</div> 5801<div class="dlist"> 5802<dl> 5803<dt class="hdlist1">Effects: </dt> 5804<dd> 5805<p>As if: <code>a <a href="#mat_mul_eq">*=</a> <a href="#rotz_mat">rotz_mat</a><<a href="#mat_traits">mat_traits<A>::rows</a>>(angle)</code>.</p> 5806</dd> 5807</dl> 5808</div> 5809<hr> 5810</div> 5811<div class="sect3"> 5812<h4 id="determinant"><code>determinant</code></h4> 5813<div class="listingblock"> 5814<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5815<div class="content"> 5816<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5817 5818 //Only enabled if: 5819 // is_mat<A>::value && mat_traits<A>::rows==mat_traits<A>::cols 5820 template <class A> 5821 mat_traits<A>::scalar_type 5822 determinant( A const & a ); 5823 5824} }</code></pre> 5825</div> 5826</div> 5827<div class="paragraph"> 5828<p>This function computes the <a href="https://en.wikipedia.org/wiki/Determinant">determinant</a> of the square matrix <code>a</code>.</p> 5829</div> 5830<hr> 5831</div> 5832<div class="sect3"> 5833<h4 id="perspective_lh"><code>perspective_lh</code></h4> 5834<div class="listingblock"> 5835<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5836<div class="content"> 5837<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5838 5839 template <class T> 5840 -unspecified-return-type- 5841 perspective_lh( T fov_y, T aspect, T zn, T zf ); 5842 5843} }</code></pre> 5844</div> 5845</div> 5846<div class="dlist"> 5847<dl> 5848<dt class="hdlist1">Returns: </dt> 5849<dd> 5850<p>A 4x4 projection matrix of unspecified type of the following form:</p> 5851<table class="tableblock frame-all grid-all" style="width: 50%;"> 5852<colgroup> 5853<col style="width: 25%;"> 5854<col style="width: 25%;"> 5855<col style="width: 25%;"> 5856<col style="width: 25%;"> 5857</colgroup> 5858<tbody> 5859<tr> 5860<td class="tableblock halign-center valign-top"><div class="verse"> <code>xs</code></div></td> 5861<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5862<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5863<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5864</tr> 5865<tr> 5866<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5867<td class="tableblock halign-center valign-top"><div class="verse"> <code>ys</code></div></td> 5868<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5869<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5870</tr> 5871<tr> 5872<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5873<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5874<td class="tableblock halign-center valign-top"><div class="verse"> <code>zf</code>/(<code>zf</code>-<code>zn</code>)</div></td> 5875<td class="tableblock halign-center valign-top"><div class="verse"> -<code>zn</code>*<code>zf</code>/(<code>zf</code>-<code>zn</code>)</div></td> 5876</tr> 5877<tr> 5878<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5879<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5880<td class="tableblock halign-center valign-top"><div class="verse"> 1</div></td> 5881<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5882</tr> 5883</tbody> 5884</table> 5885<div class="paragraph"> 5886<p>where <code>ys</code> = cot(<code>fov_y</code>/2) and <code>xs</code> = <code>ys</code>/<code>aspect</code>.</p> 5887</div> 5888</dd> 5889</dl> 5890</div> 5891<hr> 5892</div> 5893<div class="sect3"> 5894<h4 id="perspective_rh"><code>perspective_rh</code></h4> 5895<div class="listingblock"> 5896<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5897<div class="content"> 5898<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5899 5900 template <class T> 5901 -unspecified-return-type- 5902 perspective_rh( T fov_y, T aspect, T zn, T zf ); 5903 5904} }</code></pre> 5905</div> 5906</div> 5907<div class="dlist"> 5908<dl> 5909<dt class="hdlist1">Returns: </dt> 5910<dd> 5911<p>A 4x4 projection matrix of unspecified type of the following form:</p> 5912<table class="tableblock frame-all grid-all" style="width: 50%;"> 5913<colgroup> 5914<col style="width: 25%;"> 5915<col style="width: 25%;"> 5916<col style="width: 25%;"> 5917<col style="width: 25%;"> 5918</colgroup> 5919<tbody> 5920<tr> 5921<td class="tableblock halign-center valign-top"><div class="verse"> <code>xs</code></div></td> 5922<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5923<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5924<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5925</tr> 5926<tr> 5927<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5928<td class="tableblock halign-center valign-top"><div class="verse"> <code>ys</code></div></td> 5929<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5930<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5931</tr> 5932<tr> 5933<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5934<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5935<td class="tableblock halign-center valign-top"><div class="verse"> <code>zf</code>/(<code>zn</code>-<code>zf</code>)</div></td> 5936<td class="tableblock halign-center valign-top"><div class="verse"> <code>zn</code>*<code>zf</code>/(<code>zn</code>-<code>zf</code>)</div></td> 5937</tr> 5938<tr> 5939<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5940<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5941<td class="tableblock halign-center valign-top"><div class="verse"> -1</div></td> 5942<td class="tableblock halign-center valign-top"><div class="verse"> 0</div></td> 5943</tr> 5944</tbody> 5945</table> 5946<div class="paragraph"> 5947<p>where <code>ys</code> = cot(<code>fov_y</code>/2), and <code>xs</code> = <code>ys</code>/<code>aspect</code>.</p> 5948</div> 5949</dd> 5950</dl> 5951</div> 5952<hr> 5953</div> 5954<div class="sect3"> 5955<h4 id="mat_scalar_cast"><code>scalar_cast</code></h4> 5956<div class="listingblock"> 5957<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5958<div class="content"> 5959<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5960 5961 //Only enabled if: is_mat<A>::value 5962 template <class Scalar,class A> 5963 -unspecified-return_type- scalar_cast( A const & a ); 5964 5965} }</code></pre> 5966</div> 5967</div> 5968<div class="dlist"> 5969<dl> 5970<dt class="hdlist1">Returns: </dt> 5971<dd> 5972<p>A read-only <a href="#view_proxy">view proxy</a> of <code>a</code> that looks like a matrix of the same dimensions as <code>a</code>, but with <a href="#mat_traits"><code>scalar_type</code></a> <code>Scalar</code> and elements constructed from the corresponding elements of <code>a</code>.</p> 5973</dd> 5974</dl> 5975</div> 5976<hr> 5977</div> 5978<div class="sect3"> 5979<h4 id="mref"><code>mref</code></h4> 5980<div class="listingblock"> 5981<div class="title">#include <boost/qvm/mat_operations.hpp></div> 5982<div class="content"> 5983<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 5984 5985 //Only enabled if: is_mat<A>::value 5986 template <class A> 5987 -unspecified-return-type- mref( A & a ); 5988 5989} }</code></pre> 5990</div> 5991</div> 5992<div class="dlist"> 5993<dl> 5994<dt class="hdlist1">Returns: </dt> 5995<dd> 5996<p>An identity view proxy of <code>a</code>; that is, it simply accesses the elements of <code>a</code>.</p> 5997</dd> 5998</dl> 5999</div> 6000<div class="admonitionblock tip"> 6001<table> 6002<tr> 6003<td class="icon"> 6004<i class="fa icon-tip" title="Tip"></i> 6005</td> 6006<td class="content"> 6007<code>mref</code> allows calling QVM operations when <code>a</code> is of built-in type, for example a plain old C array. 6008</td> 6009</tr> 6010</table> 6011</div> 6012<hr> 6013</div> 6014</div> 6015<div class="sect2"> 6016<h3 id="_quaternion_vector_operations">Quaternion-Vector Operations</h3> 6017<div class="sect3"> 6018<h4 id="quat_vec_mul"><code>operator*</code></h4> 6019<div class="listingblock"> 6020<div class="title">#include <boost/qvm/quat_vec_operations.hpp></div> 6021<div class="content"> 6022<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6023 6024 //Only enabled if: 6025 // is_mat<A>::value && is_vec<B>::value && 6026 // mat_traits<A>::cols==vec_traits<B>::dim 6027 template <class A,class B> 6028 typename deduce_vec2<A,B,mat_traits<A>::rows>::type 6029 operator*( A const & a, B const & b ); 6030 6031} }</code></pre> 6032</div> 6033</div> 6034<div class="dlist"> 6035<dl> 6036<dt class="hdlist1">Returns: </dt> 6037<dd> 6038<p>The result of transforming the vector <code>b</code> by the quaternion <code>a</code>.</p> 6039</dd> 6040</dl> 6041</div> 6042<div class="admonitionblock note"> 6043<table> 6044<tr> 6045<td class="icon"> 6046<i class="fa icon-note" title="Note"></i> 6047</td> 6048<td class="content"> 6049The <a href="#deduce_vec2"><code>deduce_vec2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 6050</td> 6051</tr> 6052</table> 6053</div> 6054<hr> 6055</div> 6056</div> 6057<div class="sect2"> 6058<h3 id="_matrix_vector_operations">Matrix-Vector Operations</h3> 6059<div class="sect3"> 6060<h4 id="mat_vec_mul"><code>operator*</code></h4> 6061<div class="listingblock"> 6062<div class="title">#include <boost/qvm/vec_mat_operations.hpp></div> 6063<div class="content"> 6064<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6065 6066 //Only enabled if: 6067 // is_mat<A>::value && is_vec<B>::value && 6068 // mat_traits<A>::cols==vec_traits<B>::dim 6069 template <class A,class B> 6070 typename deduce_vec2<A,B,mat_traits<A>::rows>::type 6071 operator*( A const & a, B const & b ); 6072 6073} }</code></pre> 6074</div> 6075</div> 6076<div class="dlist"> 6077<dl> 6078<dt class="hdlist1">Returns: </dt> 6079<dd> 6080<p>The result of multiplying the matrix <code>a</code> and the vector <code>b</code>, where <code>b</code> is interpreted as a matrix-column. The resulting matrix-row is returned as a vector type.</p> 6081</dd> 6082</dl> 6083</div> 6084<div class="admonitionblock note"> 6085<table> 6086<tr> 6087<td class="icon"> 6088<i class="fa icon-note" title="Note"></i> 6089</td> 6090<td class="content"> 6091The <a href="#deduce_vec2"><code>deduce_vec2</code></a> template can be specialized to deduce the desired return type, given the types <code>A</code> and <code>B</code>. 6092</td> 6093</tr> 6094</table> 6095</div> 6096<hr> 6097</div> 6098<div class="sect3"> 6099<h4 id="transform_vector"><code>transform_vector</code></h4> 6100<div class="listingblock"> 6101<div class="title">#include <boost/qvm/vec_mat_operations.hpp></div> 6102<div class="content"> 6103<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6104 6105 //Only enabled if: 6106 // is_mat<A>::value && is_vec<B>::value && 6107 // mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && 6108 // vec_traits<B>::dim==3 6109 template <class A,class B> 6110 deduce_vec2<A,B,3> >::type 6111 transform_vector( A const & a, B const & b ); 6112 6113} }</code></pre> 6114</div> 6115</div> 6116<div class="dlist"> 6117<dl> 6118<dt class="hdlist1">Effects: </dt> 6119<dd> 6120<p>As if: <code>return a <a href="#mat_vec_mul">*</a> <a href="#swizzling">XYZ0</a>(b)</code>.</p> 6121</dd> 6122</dl> 6123</div> 6124<hr> 6125</div> 6126<div class="sect3"> 6127<h4 id="transform_point"><code>transform_point</code></h4> 6128<div class="listingblock"> 6129<div class="title">#include <boost/qvm/vec_mat_operations.hpp></div> 6130<div class="content"> 6131<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6132 6133 //Only enabled if: 6134 // is_mat<A>::value && is_vec<B>::value && 6135 // mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && 6136 // vec_traits<B>::dim==3 6137 template <class A,class B> 6138 deduce_vec2<A,B,3> >::type 6139 transform_point( A const & a, B const & b ); 6140 6141} }</code></pre> 6142</div> 6143</div> 6144<div class="dlist"> 6145<dl> 6146<dt class="hdlist1">Effects: </dt> 6147<dd> 6148<p>As if: <code>return a <a href="#mat_vec_mul">*</a> <a href="#swizzling">XYZ1</a>(b)</code>.</p> 6149</dd> 6150</dl> 6151</div> 6152<hr> 6153</div> 6154</div> 6155<div class="sect2"> 6156<h3 id="_matrix_to_matrix_view_proxies">Matrix-to-Matrix View Proxies</h3> 6157<div class="sect3"> 6158<h4 id="del_row"><code>del_row</code></h4> 6159<div class="listingblock"> 6160<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6161<div class="content"> 6162<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6163 6164 template <int R> 6165 -unspecified-return-type- del_row(); 6166 6167} }</code></pre> 6168</div> 6169</div> 6170<div class="paragraph"> 6171<p>The expression <code>del_row<R>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with row <code>R</code> deleted.</p> 6172</div> 6173<hr> 6174</div> 6175<div class="sect3"> 6176<h4 id="del_col"><code>del_col</code></h4> 6177<div class="listingblock"> 6178<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6179<div class="content"> 6180<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6181 6182 template <int C> 6183 -unspecified-return-type- del_col(); 6184 6185} }</code></pre> 6186</div> 6187</div> 6188<div class="paragraph"> 6189<p>The expression <code>del_col<C>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with column <code>C</code> deleted.</p> 6190</div> 6191<hr> 6192</div> 6193<div class="sect3"> 6194<h4 id="del_row_col"><code>del_row_col</code></h4> 6195<div class="listingblock"> 6196<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6197<div class="content"> 6198<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6199 6200 template <int R,int C> 6201 -unspecified-return-type- del_row_col(); 6202 6203} }</code></pre> 6204</div> 6205</div> 6206<div class="paragraph"> 6207<p>The expression <code>del_row_col<R,C>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with row <code>R</code> and column <code>C</code> deleted.</p> 6208</div> 6209<hr> 6210</div> 6211<div class="sect3"> 6212<h4 id="neg_row"><code>neg_row</code></h4> 6213<div class="listingblock"> 6214<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6215<div class="content"> 6216<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6217 6218 template <int R> 6219 -unspecified-return-type- neg_row(); 6220 6221} }</code></pre> 6222</div> 6223</div> 6224<div class="paragraph"> 6225<p>The expression <code>neg_row<R>(m)</code> returns a read-only <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with row <code>R</code> negated.</p> 6226</div> 6227<hr> 6228</div> 6229<div class="sect3"> 6230<h4 id="neg_col"><code>neg_col</code></h4> 6231<div class="listingblock"> 6232<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6233<div class="content"> 6234<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6235 6236 template <int C> 6237 -unspecified-return-type- neg_col(); 6238 6239} }</code></pre> 6240</div> 6241</div> 6242<div class="literalblock"> 6243<div class="content"> 6244<pre class="nowrap">The expression `neg_col<C>(m)` returns a read-only <<view_proxy,`view proxy`>> that looks like the matrix `m` with column `C` negated.</pre> 6245</div> 6246</div> 6247<hr> 6248</div> 6249<div class="sect3"> 6250<h4 id="swap_rows"><code>swap_rows</code></h4> 6251<div class="listingblock"> 6252<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6253<div class="content"> 6254<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6255 6256 template <int R1,int R2> 6257 -unspecified-return-type- swap_rows(); 6258 6259} }</code></pre> 6260</div> 6261</div> 6262<div class="paragraph"> 6263<p>The expression <code>swap_rows<R1,R2>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with rows <code>R1</code> and <code>R2</code> swapped.</p> 6264</div> 6265<hr> 6266</div> 6267<div class="sect3"> 6268<h4 id="swap_cols"><code>swap_cols</code></h4> 6269<div class="listingblock"> 6270<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6271<div class="content"> 6272<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6273 6274 template <int C1,int C2> 6275 -unspecified-return-type- swap_cols(); 6276 6277} }</code></pre> 6278</div> 6279</div> 6280<div class="paragraph"> 6281<p>The expression <code>swap_cols<C1,C2>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that looks like the matrix <code>m</code> with columns <code>C1</code> and <code>C2</code> swapped.</p> 6282</div> 6283<hr> 6284</div> 6285<div class="sect3"> 6286<h4 id="transposed"><code>transposed</code></h4> 6287<div class="listingblock"> 6288<div class="title">#include <boost/qvm/map_mat_mat.hpp></div> 6289<div class="content"> 6290<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6291 6292 -unspecified-return-type- transposed(); 6293 6294} }</code></pre> 6295</div> 6296</div> 6297<div class="paragraph"> 6298<p>The expression <code>transposed(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that transposes the matrix <code>m</code>.</p> 6299</div> 6300<hr> 6301</div> 6302</div> 6303<div class="sect2"> 6304<h3 id="_vector_to_matrix_view_proxies">Vector-to-Matrix View Proxies</h3> 6305<div class="sect3"> 6306<h4 id="col_mat"><code>col_mat</code></h4> 6307<div class="listingblock"> 6308<div class="title">#include <boost/qvm/map_vec_mat.hpp></div> 6309<div class="content"> 6310<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6311 6312 //Only enabled if: is_vec<A>::value 6313 template <iclass A> 6314 -unspecified-return-type- col_mat( A & a ); 6315 6316} }</code></pre> 6317</div> 6318</div> 6319<div class="paragraph"> 6320<p>The expression <code>col_mat(v)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the vector <code>v</code> as a matrix-column.</p> 6321</div> 6322<hr> 6323</div> 6324<div class="sect3"> 6325<h4 id="row_mat"><code>row_mat</code></h4> 6326<div class="listingblock"> 6327<div class="title">#include <boost/qvm/map_vec_mat.hpp></div> 6328<div class="content"> 6329<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6330 6331 //Only enabled if: is_vec<A>::value 6332 template <iclass A> 6333 -unspecified-return-type- row_mat( A & a ); 6334 6335} }</code></pre> 6336</div> 6337</div> 6338<div class="paragraph"> 6339<p>The expression <code>row_mat(v)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the vector <code>v</code> as a matrix-row.</p> 6340</div> 6341<hr> 6342</div> 6343<div class="sect3"> 6344<h4 id="translation_mat"><code>translation_mat</code></h4> 6345<div class="listingblock"> 6346<div class="title">#include <boost/qvm/map_vec_mat.hpp></div> 6347<div class="content"> 6348<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6349 6350 //Only enabled if: is_vec<A>::value 6351 template <iclass A> 6352 -unspecified-return-type- translation_mat( A & a ); 6353 6354} }</code></pre> 6355</div> 6356</div> 6357<div class="paragraph"> 6358<p>The expression <code>translation_mat(v)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the vector <code>v</code> as translation matrix of size 1 + <a href="#vec_traits"><code>vec_traits<A>::dim</code></a>.</p> 6359</div> 6360<hr> 6361</div> 6362<div class="sect3"> 6363<h4 id="diag_mat"><code>diag_mat</code></h4> 6364<div class="listingblock"> 6365<div class="title">#include <boost/qvm/map_vec_mat.hpp></div> 6366<div class="content"> 6367<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6368 6369 //Only enabled if: is_vec<A>::value 6370 template <iclass A> 6371 -unspecified-return-type- diag_mat( A & a ); 6372 6373} }</code></pre> 6374</div> 6375</div> 6376<div class="paragraph"> 6377<p>The expression <code>diag_mat(v)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the vector <code>v</code> as a square matrix of the same dimensions in which the elements of <code>v</code> appear as the main diagonal and all other elements are zero.</p> 6378</div> 6379<div class="admonitionblock tip"> 6380<table> 6381<tr> 6382<td class="icon"> 6383<i class="fa icon-tip" title="Tip"></i> 6384</td> 6385<td class="content"> 6386If <code>v</code> is a 3D vector, the expression <code>diag_mat(XYZ1(v))</code> can be used as a scaling 4D matrix. 6387</td> 6388</tr> 6389</table> 6390</div> 6391<hr> 6392</div> 6393</div> 6394<div class="sect2"> 6395<h3 id="_matrix_to_vector_view_proxies">Matrix-to-Vector View Proxies</h3> 6396<div class="sect3"> 6397<h4 id="col"><code>col</code></h4> 6398<div class="listingblock"> 6399<div class="title">#include <boost/qvm/map_mat_vec.hpp></div> 6400<div class="content"> 6401<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6402 6403 //Only enabled if: is_mat<A>::value 6404 template <int C,class A> 6405 -unspecified-return-type- col( A & a ); 6406 6407} }</code></pre> 6408</div> 6409</div> 6410<div class="paragraph"> 6411<p>The expression <code>col<C>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses column <code>C</code> of the matrix <code>m</code> as a vector.</p> 6412</div> 6413<hr> 6414</div> 6415<div class="sect3"> 6416<h4 id="row"><code>row</code></h4> 6417<div class="listingblock"> 6418<div class="title">#include <boost/qvm/map_mat_vec.hpp></div> 6419<div class="content"> 6420<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6421 6422 //Only enabled if: is_mat<A>::value 6423 template <int C,class A> 6424 -unspecified-return-type- row( A & a ); 6425 6426} }</code></pre> 6427</div> 6428</div> 6429<div class="paragraph"> 6430<p>The expression <code>row<R>(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses row <code>R</code> of the matrix <code>m</code> as a vector.</p> 6431</div> 6432<hr> 6433</div> 6434<div class="sect3"> 6435<h4 id="diag"><code>diag</code></h4> 6436<div class="listingblock"> 6437<div class="title">#include <boost/qvm/map_mat_vec.hpp></div> 6438<div class="content"> 6439<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6440 6441 //Only enabled if: is_mat<A>::value 6442 template <class A> 6443 -unspecified-return-type- diag( A & a ); 6444 6445} }</code></pre> 6446</div> 6447</div> 6448<div class="paragraph"> 6449<p>The expression <code>diag(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the main diagonal of the matrix <code>m</code> as a vector.</p> 6450</div> 6451<hr> 6452</div> 6453<div class="sect3"> 6454<h4 id="translation"><code>translation</code></h4> 6455<div class="listingblock"> 6456<div class="title">#include <boost/qvm/map_mat_vec.hpp></div> 6457<div class="content"> 6458<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6459 6460 //Only enabled if: 6461 // is_mat<A>::value && 6462 // mat_traits<A>::rows==mat_traits<A>::cols && mat_traits<A>::rows>=3 6463 template <class A> 6464 -unspecified-return-type- translation( A & a ); 6465 6466} }</code></pre> 6467</div> 6468</div> 6469<div class="paragraph"> 6470<p>The expression <code>translation(m)</code> returns an lvalue <a href="#view_proxy">view proxy</a> that accesses the translation component of the square matrix <code>m</code>, which is a vector of size <code>D</code>-1, where <code>D</code> is the size of <code>m</code>.</p> 6471</div> 6472<hr> 6473</div> 6474</div> 6475<div class="sect2"> 6476<h3 id="_exceptions">Exceptions</h3> 6477<div class="sect3"> 6478<h4 id="error"><code>error</code></h4> 6479<div class="listingblock"> 6480<div class="title">#include <boost/qvm/error.hpp></div> 6481<div class="content"> 6482<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6483 6484 struct error: virtual boost::exception, virtual std::exception { }; 6485 6486} }</code></pre> 6487</div> 6488</div> 6489<div class="paragraph"> 6490<p>This is the base for all exceptions thorwn by QVM.</p> 6491</div> 6492<hr> 6493</div> 6494<div class="sect3"> 6495<h4 id="zero_magnitude_error"><code>zero_magnitude_error</code></h4> 6496<div class="listingblock"> 6497<div class="title">#include <boost/qvm/error.hpp></div> 6498<div class="content"> 6499<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6500 6501 struct zero_magnitude_error: virtual error { }; 6502 6503} }</code></pre> 6504</div> 6505</div> 6506<div class="paragraph"> 6507<p>This exception indicates that an operation requires a vector or a quaternion with non-zero magnitude, but the computed magnitude is zero.</p> 6508</div> 6509<hr> 6510</div> 6511<div class="sect3"> 6512<h4 id="zero_determinant_error"><code>zero_determinant_error</code></h4> 6513<div class="listingblock"> 6514<div class="title">#include <boost/qvm/error.hpp></div> 6515<div class="content"> 6516<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6517 6518 struct zero_determinant_error: virtual error { }; 6519 6520} }</code></pre> 6521</div> 6522</div> 6523<div class="paragraph"> 6524<p>This exception indicates that an operation requires a matrix with non-zero determinant, but the computed determinant is zero.</p> 6525</div> 6526<hr> 6527</div> 6528</div> 6529<div class="sect2"> 6530<h3 id="_macros_and_configuration_boost_qvm">Macros and Configuration: BOOST_QVM_</h3> 6531<div class="sect3"> 6532<h4 id="BOOST_QVM_INLINE"><code>INLINE</code></h4> 6533<div class="sect4"> 6534<h5 id="_boost_qvm_inline"><code>BOOST_QVM_INLINE</code></h5> 6535<div class="listingblock"> 6536<div class="title">#include <boost/qvm/inline.hpp></div> 6537<div class="content"> 6538<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6539 6540 #ifndef BOOST_QVM_INLINE 6541 #define BOOST_QVM_INLINE inline 6542 #endif 6543 6544} }</code></pre> 6545</div> 6546</div> 6547<div class="paragraph"> 6548<p>This macro is not used directly by QVM, except as the default value of other macros from <code><boost/qvm/inline.hpp></code>. A user-defined <code>BOOST_QVM_INLINE</code> should expand to a value that is valid substitution of the <code>inline</code> keyword in function definitions.</p> 6549</div> 6550<hr> 6551</div> 6552</div> 6553<div class="sect3"> 6554<h4 id="BOOST_QVM_FORCE_INLINE"><code>FORCE_INLINE</code></h4> 6555<div class="sect4"> 6556<h5 id="_boost_qvm_force_inline"><code>BOOST_QVM_FORCE_INLINE</code></h5> 6557<div class="listingblock"> 6558<div class="title">#include <boost/qvm/inline.hpp></div> 6559<div class="content"> 6560<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6561 6562 #ifndef BOOST_QVM_FORCE_INLINE 6563 #define BOOST_QVM_FORCE_INLINE /*platform-specific*/ 6564 #endif 6565 6566} }</code></pre> 6567</div> 6568</div> 6569<div class="paragraph"> 6570<p>This macro is not used directly by QVM, except as the default value of other macros from <code><boost/qvm/inline.hpp></code>. A user-defined <code>BOOST_QVM_FORCE_INLINE</code> should expand to a value that is valid substitution of the <code>inline</code> keyword in function definitions, to indicate that the compiler must inline the function. Of course, actual inlining may or may not occur.</p> 6571</div> 6572<hr> 6573</div> 6574</div> 6575<div class="sect3"> 6576<h4 id="BOOST_QVM_INLINE_TRIVIAL"><code>INLINE_TRIVIAL</code></h4> 6577<div class="sect4"> 6578<h5 id="_boost_qvm_inline_trivial"><code>BOOST_QVM_INLINE_TRIVIAL</code></h5> 6579<div class="listingblock"> 6580<div class="title">#include <boost/qvm/inline.hpp></div> 6581<div class="content"> 6582<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6583 6584 #ifndef BOOST_QVM_INLINE_TRIVIAL 6585 #define BOOST_QVM_INLINE_TRIVIAL BOOST_QVM_FORCE_INLINE 6586 #endif 6587 6588} }</code></pre> 6589</div> 6590</div> 6591<div class="paragraph"> 6592<p>QVM uses <code>BOOST_QVM_INLINE_TRIVIAL</code> 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.</p> 6593</div> 6594<hr> 6595</div> 6596</div> 6597<div class="sect3"> 6598<h4 id="BOOST_QVM_INLINE_CRITICAL"><code>INLINE_CRITICAL</code></h4> 6599<div class="sect4"> 6600<h5 id="_boost_qvm_inline_critical"><code>BOOST_QVM_INLINE_CRITICAL</code></h5> 6601<div class="listingblock"> 6602<div class="title">#include <boost/qvm/inline.hpp></div> 6603<div class="content"> 6604<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6605 6606 #ifndef BOOST_QVM_INLINE_CRITICAL 6607 #define BOOST_QVM_INLINE_CRITICAL BOOST_QVM_FORCE_INLINE 6608 #endif 6609 6610} }</code></pre> 6611</div> 6612</div> 6613<div class="paragraph"> 6614<p>QVM uses <code>BOOST_QVM_INLINE_CRITICAL</code> in definitions of functions that are critical for the overall performance of the library, such as functions that access individual vector and matrix elements.</p> 6615</div> 6616<hr> 6617</div> 6618</div> 6619<div class="sect3"> 6620<h4 id="BOOST_QVM_INLINE_OPERATIONS"><code>INLINE_OPERATIONS</code></h4> 6621<div class="sect4"> 6622<h5 id="_boost_qvm_inline_operations"><code>BOOST_QVM_INLINE_OPERATIONS</code></h5> 6623<div class="listingblock"> 6624<div class="title">#include <boost/qvm/inline.hpp></div> 6625<div class="content"> 6626<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6627 6628 #ifndef BOOST_QVM_INLINE_OPERATIONS 6629 #define BOOST_QVM_INLINE_OPERATIONS BOOST_QVM_INLINE 6630 #endif 6631 6632} }</code></pre> 6633</div> 6634</div> 6635<div class="paragraph"> 6636<p>QVM uses <code>BOOST_QVM_INLINE_OPERATIONS</code> in definitions of functions that implement various high-level operations, such as matrix multiplication, computing the magnitude of a vector, etc.</p> 6637</div> 6638<hr> 6639</div> 6640</div> 6641<div class="sect3"> 6642<h4 id="BOOST_QVM_INLINE_RECURSION"><code>INLINE_RECURSION</code></h4> 6643<div class="sect4"> 6644<h5 id="_boost_qvm_inline_recursion"><code>BOOST_QVM_INLINE_RECURSION</code></h5> 6645<div class="listingblock"> 6646<div class="title">#include <boost/qvm/inline.hpp></div> 6647<div class="content"> 6648<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6649 6650 #ifndef BOOST_QVM_INLINE_RECURSION 6651 #define BOOST_QVM_INLINE_RECURSION BOOST_QVM_INLINE_OPERATIONS 6652 #endif 6653 6654} }</code></pre> 6655</div> 6656</div> 6657<div class="paragraph"> 6658<p>QVM uses <code>BOOST_QVM_INLINE_RECURSION</code> 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 <a href="#BOOST_QVM_INLINE_CRITICAL"><code>BOOST_QVM_INLINE_CRITICAL</code></a>).</p> 6659</div> 6660<hr> 6661</div> 6662</div> 6663<div class="sect3"> 6664<h4 id="BOOST_QVM_ASSERT"><code>ASSERT</code></h4> 6665<div class="sect4"> 6666<h5 id="_boost_qvm_assert"><code>BOOST_QVM_ASSERT</code></h5> 6667<div class="listingblock"> 6668<div class="title">#include <boost/qvm/assert.hpp></div> 6669<div class="content"> 6670<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6671 6672#ifndef BOOST_QVM_ASSERT 6673#include <boost/assert.hpp> 6674#define BOOST_QVM_ASSERT BOOST_ASSERT 6675#endif 6676 6677} }</code></pre> 6678</div> 6679</div> 6680<div class="paragraph"> 6681<p>This is the macro QVM uses to assert on precondition violations and logic errors. A user-defined <code>BOOST_QVM_ASSERT</code> should have the semantics of the standard <code>assert</code>.</p> 6682</div> 6683<hr> 6684</div> 6685</div> 6686<div class="sect3"> 6687<h4 id="BOOST_QVM_STATIC_ASSERT"><code>STATIC_ASSERT</code></h4> 6688<div class="sect4"> 6689<h5 id="_boost_qvm_static_assert"><code>BOOST_QVM_STATIC_ASSERT</code></h5> 6690<div class="listingblock"> 6691<div class="title">#include <boost/qvm/static_assert.hpp></div> 6692<div class="content"> 6693<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6694 6695 #ifndef BOOST_QVM_STATIC_ASSERT 6696 #include <boost/static_assert.hpp> 6697 #define BOOST_QVM_STATIC_ASSERT BOOST_STATIC_ASSERT 6698 #endif 6699 6700} }</code></pre> 6701</div> 6702</div> 6703<div class="paragraph"> 6704<p>All static assertions in QVM use the <code>BOOST_QVM_STATIC_ASSERT</code> macro.</p> 6705</div> 6706<hr> 6707</div> 6708</div> 6709<div class="sect3"> 6710<h4 id="BOOST_QVM_THROW_EXCEPTION"><code>THROW_EXCEPTION</code></h4> 6711<div class="sect4"> 6712<h5 id="_boost_qvm_throw_exception"><code>BOOST_QVM_THROW_EXCEPTION</code></h5> 6713<div class="listingblock"> 6714<div class="title">#include <boost/qvm/throw_exception.hpp></div> 6715<div class="content"> 6716<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace boost { namespace qvm { 6717 6718 #ifndef BOOST_QVM_THROW_EXCEPTION 6719 #include <boost/throw_exception.hpp> 6720 #define BOOST_QVM_THROW_EXCEPTION BOOST_THROW_EXCEPTION 6721 #endif 6722 6723} }</code></pre> 6724</div> 6725</div> 6726<div class="paragraph"> 6727<p>This macro is used whenever QVM throws an exception. Users who override the standard <code>BOOST_QVM_THROW_EXCEPTION</code> behavior must ensure that when invoked, the substituted implementation does not return control to the caller. Below is a list of all QVM functions that invoke <code>BOOST_QVM_THROW_EXCEPTION</code>:</p> 6728</div> 6729<div class="ulist"> 6730<ul> 6731<li> 6732<p>Quaternion operations:</p> 6733<div class="ulist"> 6734<ul> 6735<li> 6736<p><a href="#quat_inverse"><code>inverse</code></a></p> 6737</li> 6738<li> 6739<p><a href="#rot_quat"><code>rot_quat</code></a></p> 6740</li> 6741<li> 6742<p><a href="#quat_normalize"><code>normalize</code></a></p> 6743</li> 6744<li> 6745<p><a href="#quat_normalized"><code>normalized</code></a></p> 6746</li> 6747</ul> 6748</div> 6749</li> 6750<li> 6751<p>Vector operations:</p> 6752<div class="ulist"> 6753<ul> 6754<li> 6755<p><a href="#vec_normalize"><code>normalize</code></a></p> 6756</li> 6757<li> 6758<p><a href="#vec_normalized"><code>normalized</code></a></p> 6759</li> 6760</ul> 6761</div> 6762</li> 6763<li> 6764<p>Matrix operations:</p> 6765<div class="ulist"> 6766<ul> 6767<li> 6768<p><a href="#mat_inverse"><code>inverse</code></a></p> 6769</li> 6770<li> 6771<p><a href="#rot_mat"><code>rot_mat</code></a></p> 6772</li> 6773</ul> 6774</div> 6775</li> 6776</ul> 6777</div> 6778</div> 6779</div> 6780</div> 6781</div> 6782</div> 6783<div class="sect1"> 6784<h2 id="rationale">Design Rationale</h2> 6785<div class="sectionbody"> 6786<div class="paragraph"> 6787<p>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.</p> 6788</div> 6789<div class="paragraph"> 6790<p>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.</p> 6791</div> 6792<div class="paragraph"> 6793<p>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.</p> 6794</div> 6795<div class="paragraph"> 6796<p>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.</p> 6797</div> 6798<div class="paragraph"> 6799<p>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.</p> 6800</div> 6801</div> 6802</div> 6803<div class="sect1"> 6804<h2 id="_code_generator">Code Generator</h2> 6805<div class="sectionbody"> 6806<div class="paragraph"> 6807<p>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.</p> 6808</div> 6809<div class="paragraph"> 6810<p>The code generator is a command-line utility program. Its source code can be found in the <code>boost/libs/qvm/gen</code> directory. It was used to generate the following headers that ship with QVM:</p> 6811</div> 6812<div class="ulist"> 6813<ul> 6814<li> 6815<p>2D, 3D and 4D matrix operations:</p> 6816<div class="ulist"> 6817<ul> 6818<li> 6819<p><code>boost/qvm/gen/mat_operations2.hpp</code> (matrices of size 2x2, 2x1 and 1x2, included by <code>boost/qvm/mat_operations2.hpp</code>)</p> 6820</li> 6821<li> 6822<p><code>boost/qvm/gen/mat_operations3.hpp</code> (matrices of size 3x3, 3x1 and 1x3, included by <code>boost/qvm/mat_operations3.hpp</code>)</p> 6823</li> 6824<li> 6825<p><code>boost/qvm/gen/mat_operations4.hpp</code> (matrices of size 4x4, 4x1 and 1x4, included by <code>boost/qvm/mat_operations4.hpp</code>)</p> 6826</li> 6827</ul> 6828</div> 6829</li> 6830<li> 6831<p>2D, 3D and 4D vector operations:</p> 6832<div class="ulist"> 6833<ul> 6834<li> 6835<p><code>boost/qvm/gen/v2.hpp</code> (included by <code>boost/qvm/vec_operations2.hpp</code>)</p> 6836</li> 6837<li> 6838<p><code>boost/qvm/gen/v3.hpp</code> (included by <code>boost/qvm/vec_operations3.hpp</code>)</p> 6839</li> 6840<li> 6841<p><code>boost/qvm/gen/v4.hpp</code> (included by <code>boost/qvm/vec_operations4.hpp</code>)</p> 6842</li> 6843</ul> 6844</div> 6845</li> 6846<li> 6847<p>2D, 3D and 4D vector-matrix operations:</p> 6848<div class="ulist"> 6849<ul> 6850<li> 6851<p><code>boost/qvm/gen/vm2.hpp</code> (included by <code>boost/qvm/vec_mat_operations2.hpp</code>)</p> 6852</li> 6853<li> 6854<p><code>boost/qvm/gen/vm3.hpp</code> (included by <code>boost/qvm/vec_mat_operations3.hpp</code>)</p> 6855</li> 6856<li> 6857<p><code>boost/qvm/gen/vm4.hpp</code> (included by <code>boost/qvm/vec_mat_operations4.hpp</code>)</p> 6858</li> 6859</ul> 6860</div> 6861</li> 6862<li> 6863<p>2D, 3D and 4D vector swizzling operations:</p> 6864<div class="ulist"> 6865<ul> 6866<li> 6867<p><code>boost/qvm/gen/sw2.hpp</code> (included by <code>boost/qvm/swizzle2.hpp</code>)</p> 6868</li> 6869<li> 6870<p><code>boost/qvm/gen/sw3.hpp</code> (included by <code>boost/qvm/swizzle3.hpp</code>)</p> 6871</li> 6872<li> 6873<p><code>boost/qvm/gen/sw4.hpp</code> (included by <code>boost/qvm/swizzle4.hpp</code>)</p> 6874</li> 6875</ul> 6876</div> 6877</li> 6878</ul> 6879</div> 6880<div class="paragraph"> 6881<p>Any such generated headers must be included before the corresponding generic header file is included. For example, if one creates a header <code>boost/qvm/gen/m5.hpp</code>, it must be included before <code>boost/qvm/mat_operations.hpp</code> in included. However, the generic headers (<code>boost/qvm/mat_operations.hpp</code>, <code>boost/qvm/vec_operations.hpp</code>, <code>boost/qvm/vec_mat_operations.hpp</code> and <code>boost/qvm/swizzle.hpp</code>) already include the generated headers from the list above, so the generated headers don’t need to be included manually.</p> 6882</div> 6883<div class="admonitionblock note"> 6884<table> 6885<tr> 6886<td class="icon"> 6887<i class="fa icon-note" title="Note"></i> 6888</td> 6889<td class="content"> 6890headers under <code>boost/qvm/gen</code> are not part of the public interface of QVM. For example, <code>boost/qvm/gen/mat_operations2.hpp</code> should not be included directly; <code>#include <boost/qvm/mat_operations2.hpp></code> instead. 6891</td> 6892</tr> 6893</table> 6894</div> 6895</div> 6896</div> 6897<div class="sect1"> 6898<h2 id="_known_quirks_and_issues">Known Quirks and Issues</h2> 6899<div class="sectionbody"> 6900<div class="sect2"> 6901<h3 id="_capturing_view_proxies_with_auto">Capturing View Proxies with <code>auto</code></h3> 6902<div class="paragraph"> 6903<p>By design, <a href="#view_proxy">view proxies</a> must not return temporary objects. They return reference to an argument they take by (<code>const</code>) reference, cast to reference of unspecified type that is not copyable. Because of this, the return value of a view proxy can not be captured by value with <code>auto</code>:</p> 6904</div> 6905<div class="listingblock"> 6906<div class="content"> 6907<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">auto tr = transposed(m); //Error: the return type of transposed can not be copied.</code></pre> 6908</div> 6909</div> 6910<div class="paragraph"> 6911<p>The correct use of auto with view proxies is:</p> 6912</div> 6913<div class="listingblock"> 6914<div class="content"> 6915<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">auto & tr = transposed(m);</code></pre> 6916</div> 6917</div> 6918<div class="admonitionblock note"> 6919<table> 6920<tr> 6921<td class="icon"> 6922<i class="fa icon-note" title="Note"></i> 6923</td> 6924<td class="content"> 6925Many 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 <code>auto</code>. 6926</td> 6927</tr> 6928</table> 6929</div> 6930<hr> 6931</div> 6932<div class="sect2"> 6933<h3 id="_binding_qvm_overloads_from_an_unrelated_namespace">Binding QVM Overloads From an Unrelated Namespace</h3> 6934<div class="paragraph"> 6935<p>The operator overloads in namespace <code>boost::qvm</code> are designed to work with user-defined types. Typically it is sufficient to make these operators available in the namespace where the operator is used, by <code>using namespace boost::qvm</code>. A problem arises if the scope that uses the operator is not controlled by the user. For example:</p> 6936</div> 6937<div class="listingblock"> 6938<div class="content"> 6939<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace ns1 { 6940 6941 struct float2 { float x, y; }; 6942 6943} 6944 6945namespace ns2 { 6946 6947 using namespace boost::qvm; 6948 6949 void f() { 6950 ns1::float2 a, b; 6951 a==b; //OK 6952 ns1::float2 arr1[2], arr2[2]; 6953 std::equal(arr1,arr1+2,arr2); //Error: operator== is inaccessible from namespace std 6954 } 6955 6956}</code></pre> 6957</div> 6958</div> 6959<div class="paragraph"> 6960<p>In the <code>std::equal</code> expression above, even though <code>boost::qvm::operator==</code> is made visible in namespace <code>ns2</code> by <code>using namespace boost::qvm</code>, the call originates from namespace <code>std</code>. In this case the compiler can’t bind <code>boost::qvm::operator==</code> because only namespace <code>ns1</code> is visible through ADL, and it does not contain a suitable declaration. The solution is to declare <code>operator==</code> in namespace ns1, which can be done like this:</p> 6961</div> 6962<div class="listingblock"> 6963<div class="content"> 6964<pre class="highlight nowrap"><code class="language-c++" data-lang="c++">namespace ns1 { 6965 6966 using boost::qvm::operator==; 6967 6968}</code></pre> 6969</div> 6970</div> 6971<hr> 6972</div> 6973<div class="sect2"> 6974<h3 id="_link_errors_when_calling_math_functions_with_int_arguments">Link Errors When Calling Math Functions with <code>int</code> Arguments</h3> 6975<div class="paragraph"> 6976<p>QVM does not call standard math functions (e.g. sin, cos, etc.) directly. Instead, it calls function templates declared in <code>boost/qvm/math.hpp</code> in namespace <code>boost::qvm</code>. This allows the user to specialize these templates for user-defined scalar types.</p> 6977</div> 6978<div class="paragraph"> 6979<p>QVM itself defines specializations of the math function templates only for <code>float</code> and <code>double</code>, 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 <code>double</code> when passing arguments of lesser types, which would be suboptimal.</p> 6980</div> 6981<div class="paragraph"> 6982<p>Because of this, a call to e.g. <code><a href="#rot_mat">rot_mat</a>(axis,1)</code> will compile successfully but fail to link, since it calls e.g. <code>boost::qvm::sin<int></code>, 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 <code>rot_mat(axis,1.0f)</code> instead.</p> 6983</div> 6984</div> 6985</div> 6986</div> 6987<div class="sect1"> 6988<h2 id="_distribution">Distribution</h2> 6989<div class="sectionbody"> 6990<div class="paragraph"> 6991<p>QVM is part of <a href="https://www.boost.org/">Boost</a> and is distributed under the <a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License, Version 1.0</a>.</p> 6992</div> 6993<div class="paragraph"> 6994<p>The source code is available in <a href="https://github.com/boostorg/qvm">QVM GitHub repository</a>.</p> 6995</div> 6996<div class="paragraph"> 6997<p>© 2008-2018 Emil Dotchevski and Reverge Studios, Inc.</p> 6998</div> 6999</div> 7000</div> 7001<div class="sect1"> 7002<h2 id="_portability">Portability</h2> 7003<div class="sectionbody"> 7004<div class="paragraph"> 7005<p>See the <a href="https://travis-ci.org/boostorg/qvm">QVM Travis CI Builds</a>.</p> 7006</div> 7007</div> 7008</div> 7009<div class="sect1"> 7010<h2 id="_feedback_support">Feedback / Support</h2> 7011<div class="sectionbody"> 7012<div class="paragraph"> 7013<p>Please use the <a href="https://lists.boost.org/mailman/listinfo.cgi/boost">Boost Developers mailing list</a>.</p> 7014</div> 7015</div> 7016</div> 7017<div class="sect1"> 7018<h2 id="_qa">Q&A</h2> 7019<div class="sectionbody"> 7020<div class="qlist qanda"> 7021<ol> 7022<li> 7023<p><em>What is the motivation behind QVM? Why not just use uBLAS/Eigen/CML/GLM/etc?</em></p> 7024<p>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).</p> 7025</li> 7026<li> 7027<p><em>How does the <code>qvm::<a href="#vec">vec</a></code> (or <code>qvm::<a href="#mat">mat</a></code>, or <code>qvm::<a href="#quat">quat</a></code>) template compare to vector types from other libraries?</em></p> 7028<p>The <code>qvm::vec</code> 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. <code>D3DVECTOR</code>), while the <code>qvm::vec</code> 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 <a href="#deduce_mat2"><code>deduce_mat2</code></a> hasn’t been specialized, calling <a href="#cross"><code>cross</code></a> with a user-defined type <code>vec3</code> and a user-defined type <code>float3</code> returns a <code>qvm::vec</code>.</p> 7029</li> 7030<li> 7031<p><em>Why doesn’t QVM use [] or () to access vector and matrix elements?</em></p> 7032<p>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 <code>operator[]</code> or <code>operator()</code> they are available for use with other QVM functions, but QVM defines its own mechanisms for <a href="#quat_access">accessing quaternion elements</a>, <a href="#vec_access">accessing vector elements</a> (as well as <a href="#swizzling">swizzling</a>), and <a href="#mat_access">accessing matrix elements</a>.</p> 7033</li> 7034</ol> 7035</div> 7036<hr> 7037<div class="paragraph text-right"> 7038<p>Documentation rendered by <a href="https://asciidoctor.org/">Asciidoctor</a> with <a href="https://github.com/zajo/asciidoctor_skin">these customizations</a>.</p> 7039</div> 7040<div class="paragraph text-right"> 7041<p>© 2008-2020 Emil Dotchevski and Reverge Studios, Inc.</p> 7042</div> 7043</div> 7044</div> 7045</div> 7046<div id="footer"> 7047<div id="footer-text"> 7048</div> 7049</div> 7050</body> 7051</html>