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