<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>[linear.algebra]R1: A proposal to add linear algebra support to the C++ standard library</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li .secno { font-size: 85%; }
	.toc > li li li li li { font-size:   85%;    }
	.toc > li li li li li .secno { font-size: 100%; }

	/* @supports not (display:grid) { */
		.toc > li             { margin: 1.5rem 0;    }
		.toc > li li          { margin: 0.3rem 0;    }
		.toc > li li li       { margin-left: 2rem;   }

		/* Section numbers in a column of their own */
		.toc .secno {
			float: left;
			width: 4rem;
			white-space: nowrap;
		}

		.toc li {
			clear: both;
		}

		:not(li) > .toc              { margin-left:  5rem; }
		.toc .secno                  { margin-left: -5rem; }
		.toc > li li li .secno       { margin-left: -7rem; }
		.toc > li li li li .secno    { margin-left: -9rem; }
		.toc > li li li li li .secno { margin-left: -11rem; }

		/* Tighten up indentation in narrow ToCs */
		@media (max-width: 30em) {
			:not(li) > .toc              { margin-left:  4rem; }
			.toc .secno                  { margin-left: -4rem; }
			.toc > li li li              { margin-left:  1rem; }
			.toc > li li li .secno       { margin-left: -5rem; }
			.toc > li li li li .secno    { margin-left: -6rem; }
			.toc > li li li li li .secno { margin-left: -7rem; }
		}
	/* } */

	@supports (display:grid) {
		/* Use #toc over .toc to override non-@supports rules. */
		#toc {
			display: grid;
			align-content: start;
			grid-template-columns: auto 1fr;
			grid-column-gap: 1rem;
			column-gap: 1rem;
			grid-row-gap: .6rem;
			row-gap: .6rem;
		}
		#toc h2 {
			grid-column: 1 / -1;
			margin-bottom: 0;
		}
		#toc ol,
		#toc li,
		#toc a {
			display: contents;
			/* Switch <a> to subgrid when supported */
		}
		#toc span {
			margin: 0;
		}
		#toc > .toc > li > a > span {
			/* The spans of the top-level list,
			   comprising the first items of each top-level section. */
			margin-top: 1.1rem;
		}
		#toc#toc .secno { /* Ugh, need more specificity to override base.css */
			grid-column: 1;
			width: auto;
			margin-left: 0;
		}
		#toc .content {
			grid-column: 2;
			width: auto;
			margin-right: 1rem;
		}
		#toc .content:hover {
			background: rgba(75%, 75%, 75%, .25);
			border-bottom: 3px solid #054572;
			margin-bottom: -3px;
		}
		#toc li li li .content {
			margin-left: 1rem;
		}
		#toc li li li li .content {
			margin-left: 2rem;
		}
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }
  </style>
  <meta content="Bikeshed version c03af8da7325f5ae3f9ca742161b5d270bbce12f" name="generator">
  <link href="http://wg21.link/P1385" rel="canonical">
  <link href="https://isocpp.org/favicon.ico" rel="icon">
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
c-[a] { color: #990055 } /* Keyword.Declaration */
c-[b] { color: #990055 } /* Keyword.Type */
c-[c] { color: #708090 } /* Comment */
c-[d] { color: #708090 } /* Comment.Multiline */
c-[e] { color: #0077aa } /* Name.Attribute */
c-[f] { color: #669900 } /* Name.Tag */
c-[g] { color: #222222 } /* Name.Variable */
c-[k] { color: #990055 } /* Keyword */
c-[l] { color: #000000 } /* Literal */
c-[m] { color: #000000 } /* Literal.Number */
c-[n] { color: #0077aa } /* Name */
c-[o] { color: #999999 } /* Operator */
c-[p] { color: #999999 } /* Punctuation */
c-[s] { color: #a67f59 } /* Literal.String */
c-[t] { color: #a67f59 } /* Literal.String.Single */
c-[u] { color: #a67f59 } /* Literal.String.Double */
c-[cp] { color: #708090 } /* Comment.Preproc */
c-[c1] { color: #708090 } /* Comment.Single */
c-[cs] { color: #708090 } /* Comment.Special */
c-[kc] { color: #990055 } /* Keyword.Constant */
c-[kn] { color: #990055 } /* Keyword.Namespace */
c-[kp] { color: #990055 } /* Keyword.Pseudo */
c-[kr] { color: #990055 } /* Keyword.Reserved */
c-[ld] { color: #000000 } /* Literal.Date */
c-[nc] { color: #0077aa } /* Name.Class */
c-[no] { color: #0077aa } /* Name.Constant */
c-[nd] { color: #0077aa } /* Name.Decorator */
c-[ni] { color: #0077aa } /* Name.Entity */
c-[ne] { color: #0077aa } /* Name.Exception */
c-[nf] { color: #0077aa } /* Name.Function */
c-[nl] { color: #0077aa } /* Name.Label */
c-[nn] { color: #0077aa } /* Name.Namespace */
c-[py] { color: #0077aa } /* Name.Property */
c-[ow] { color: #999999 } /* Operator.Word */
c-[mb] { color: #000000 } /* Literal.Number.Bin */
c-[mf] { color: #000000 } /* Literal.Number.Float */
c-[mh] { color: #000000 } /* Literal.Number.Hex */
c-[mi] { color: #000000 } /* Literal.Number.Integer */
c-[mo] { color: #000000 } /* Literal.Number.Oct */
c-[sb] { color: #a67f59 } /* Literal.String.Backtick */
c-[sc] { color: #a67f59 } /* Literal.String.Char */
c-[sd] { color: #a67f59 } /* Literal.String.Doc */
c-[se] { color: #a67f59 } /* Literal.String.Escape */
c-[sh] { color: #a67f59 } /* Literal.String.Heredoc */
c-[si] { color: #a67f59 } /* Literal.String.Interpol */
c-[sx] { color: #a67f59 } /* Literal.String.Other */
c-[sr] { color: #a67f59 } /* Literal.String.Regex */
c-[ss] { color: #a67f59 } /* Literal.String.Symbol */
c-[vc] { color: #0077aa } /* Name.Variable.Class */
c-[vg] { color: #0077aa } /* Name.Variable.Global */
c-[vi] { color: #0077aa } /* Name.Variable.Instance */
c-[il] { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">[linear.algebra]R1<br>A proposal to add linear algebra support to the C++ standard library</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Working Draft, <time class="dt-updated" datetime="2019-03-10">2019-03-10</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="https://github.com/BobSteagall/wg21/blob/master/linear_algebra/papers/P1385R1.html">https://github.com/BobSteagall/wg21/blob/master/linear_algebra/papers/P1385R1.html</a>
     <dt>Latest published version:
     <dd><a href="http://wg21.link/P1385">http://wg21.link/P1385</a>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:guy@hatcat.com">Guy Davidson</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:bob.steagall.cpp@gmail.com">Bob Steagall</a>
     <dt>Project:
     <dd>ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
     <dt>Audience:
     <dd>SG14, LEWG
     <dt>Previous version:
     <dd><a href="http://wg21.link/P1385R0">http://wg21.link/P1385R0</a>
     <dt>Strawman implementation:
     <dd><a href="https://github.com/BobSteagall/wg21/tree/master/linear_algebra/code">https://github.com/BobSteagall/wg21/tree/master/linear_algebra/code</a>
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>This document proposes an interface specification for a set of fundamental linear algebra facilities in the standard C++ library.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#introduction"><span class="secno">1</span> <span class="content">Introduction</span></a>
    <li><a href="#goals"><span class="secno">2</span> <span class="content">Goals</span></a>
    <li>
     <a href="#definitions"><span class="secno">3</span> <span class="content">Definitions</span></a>
     <ol class="toc">
      <li><a href="#mathematical-terms"><span class="secno">3.1</span> <span class="content">Mathematical Terms</span></a>
      <li><a href="#terms-pertaining-to-c-types"><span class="secno">3.2</span> <span class="content">Terms Pertaining to C++ Types</span></a>
      <li>
       <a href="#overloaded-terms"><span class="secno">3.3</span> <span class="content">Overloaded Terms</span></a>
       <ol class="toc">
        <li><a href="#matrix"><span class="secno">3.3.1</span> <span class="content">Matrix</span></a>
        <li><a href="#vector"><span class="secno">3.3.2</span> <span class="content">Vector</span></a>
        <li><a href="#dimension"><span class="secno">3.3.3</span> <span class="content">Dimension</span></a>
        <li><a href="#rank"><span class="secno">3.3.4</span> <span class="content">Rank</span></a>
       </ol>
     </ol>
    <li>
     <a href="#scope"><span class="secno">4</span> <span class="content">Scope</span></a>
     <ol class="toc">
      <li><a href="#functionality"><span class="secno">4.1</span> <span class="content">Functionality</span></a>
      <li><a href="#considered-but-excluded"><span class="secno">4.2</span> <span class="content">Considered but Excluded</span></a>
     </ol>
    <li>
     <a href="#design-aspects"><span class="secno">5</span> <span class="content">Design Aspects</span></a>
     <ol class="toc">
      <li><a href="#memory-source"><span class="secno">5.1</span> <span class="content">Memory Source</span></a>
      <li><a href="#addressing-model"><span class="secno">5.2</span> <span class="content">Addressing Model</span></a>
      <li><a href="#memory-ownership"><span class="secno">5.3</span> <span class="content">Memory Ownership</span></a>
      <li><a href="#capacity-and-resizability"><span class="secno">5.4</span> <span class="content">Capacity and Resizability</span></a>
      <li><a href="#element-layout"><span class="secno">5.5</span> <span class="content">Element Layout</span></a>
      <li><a href="#element-access-and-indexing"><span class="secno">5.6</span> <span class="content">Element Access and Indexing</span></a>
      <li><a href="#element-type"><span class="secno">5.7</span> <span class="content">Element Type</span></a>
      <li><a href="#mixed-element-type-expressions"><span class="secno">5.8</span> <span class="content">Mixed-Element-Type Expressions</span></a>
      <li><a href="#mixed-engine-expressions"><span class="secno">5.9</span> <span class="content">Mixed-Engine Expressions</span></a>
      <li><a href="#arithmetic-customization"><span class="secno">5.10</span> <span class="content">Arithmetic Customization</span></a>
      <li><a href="#linear-algebra-and-constexpr"><span class="secno">5.11</span> <span class="content">Linear Algebra and <code class="highlight"><c- k>constexpr</c-></code></span></a>
     </ol>
    <li>
     <a href="#interface-design-description"><span class="secno">6</span> <span class="content">Interface Design Description</span></a>
     <ol class="toc">
      <li><a href="#overview"><span class="secno">6.1</span> <span class="content">Overview</span></a>
      <li><a href="#element-promotion-helper-traits"><span class="secno">6.2</span> <span class="content">Element Promotion Helper Traits</span></a>
      <li><a href="#element-promotion-traits"><span class="secno">6.3</span> <span class="content">Element Promotion Traits</span></a>
      <li>
       <a href="#engine-types"><span class="secno">6.4</span> <span class="content">Engine Types</span></a>
       <ol class="toc">
        <li><a href="#fixed-size-engine"><span class="secno">6.4.1</span> <span class="content">Fixed-Size Engine</span></a>
        <li><a href="#dynamically-resizable-engine"><span class="secno">6.4.2</span> <span class="content">Dynamically-Resizable Engine</span></a>
        <li><a href="#transpose-engine"><span class="secno">6.4.3</span> <span class="content">Transpose Engine</span></a>
       </ol>
      <li>
       <a href="#engine-promotion-traits"><span class="secno">6.5</span> <span class="content">Engine Promotion Traits</span></a>
       <ol class="toc">
        <li><a href="#for-negation"><span class="secno">6.5.1</span> <span class="content">For Negation</span></a>
        <li><a href="#for-addition"><span class="secno">6.5.2</span> <span class="content">For Addition</span></a>
        <li><a href="#for-subtraction"><span class="secno">6.5.3</span> <span class="content">For Subtraction</span></a>
        <li><a href="#for-multiplication"><span class="secno">6.5.4</span> <span class="content">For Multiplication</span></a>
       </ol>
      <li>
       <a href="#mathematical-types"><span class="secno">6.6</span> <span class="content">Mathematical Types</span></a>
       <ol class="toc">
        <li><a href="#helper-traits"><span class="secno">6.6.1</span> <span class="content">Helper Traits</span></a>
        <li><a href="#column-vector"><span class="secno">6.6.2</span> <span class="content">Column Vector</span></a>
        <li><a href="#row-vector"><span class="secno">6.6.3</span> <span class="content">Row Vector</span></a>
        <li><a href="#matrix①"><span class="secno">6.6.4</span> <span class="content">Matrix</span></a>
       </ol>
      <li>
       <a href="#matrix-arithmetic-traits"><span class="secno">6.7</span> <span class="content">Matrix Arithmetic Traits</span></a>
       <ol class="toc">
        <li><a href="#negation-traits"><span class="secno">6.7.1</span> <span class="content">Negation Traits</span></a>
        <li><a href="#addition-traits"><span class="secno">6.7.2</span> <span class="content">Addition Traits</span></a>
        <li><a href="#subtraction-traits"><span class="secno">6.7.3</span> <span class="content">Subtraction Traits</span></a>
        <li><a href="#multiplication-traits"><span class="secno">6.7.4</span> <span class="content">Multiplication Traits</span></a>
       </ol>
      <li><a href="#operator-traits"><span class="secno">6.8</span> <span class="content">Operator Traits</span></a>
      <li><a href="#operator-traits-promotion"><span class="secno">6.9</span> <span class="content">Operator Traits Promotion</span></a>
      <li>
       <a href="#arithmetic-operators"><span class="secno">6.10</span> <span class="content">Arithmetic Operators</span></a>
       <ol class="toc">
        <li><a href="#negation-operator"><span class="secno">6.10.1</span> <span class="content">Negation Operator</span></a>
        <li><a href="#addition-operator"><span class="secno">6.10.2</span> <span class="content">Addition Operator</span></a>
        <li><a href="#subtraction-operator"><span class="secno">6.10.3</span> <span class="content">Subtraction Operator</span></a>
        <li><a href="#multiplication-operator"><span class="secno">6.10.4</span> <span class="content">Multiplication Operator</span></a>
       </ol>
      <li><a href="#type-aliases"><span class="secno">6.11</span> <span class="content">Type Aliases</span></a>
      <li><a href="#expression-results"><span class="secno">6.12</span> <span class="content">Expression Results</span></a>
     </ol>
    <li>
     <a href="#how-does-it-work"><span class="secno">7</span> <span class="content">How Does it Work?</span></a>
     <ol class="toc">
      <li>
       <a href="#in-more-detail"><span class="secno">7.1</span> <span class="content">In More Detail</span></a>
       <ol class="toc">
        <li><a href="#calling-an-operator"><span class="secno">7.1.1</span> <span class="content">Calling an Operator</span></a>
        <li><a href="#selecting-the-operator-traits"><span class="secno">7.1.2</span> <span class="content">Selecting the Operator Traits</span></a>
        <li><a href="#selecting-the-multiplication-traits"><span class="secno">7.1.3</span> <span class="content">Selecting the Multiplication Traits</span></a>
        <li><a href="#selecting-the-engine-type"><span class="secno">7.1.4</span> <span class="content">Selecting the Engine Type</span></a>
        <li><a href="#the-fully-instantiated-multiplication-traits"><span class="secno">7.1.5</span> <span class="content">The Fully Instantiated Multiplication Traits</span></a>
       </ol>
     </ol>
    <li>
     <a href="#customization"><span class="secno">8</span> <span class="content">Customization</span></a>
     <ol class="toc">
      <li><a href="#integrating-a-new-element-type"><span class="secno">8.1</span> <span class="content">Integrating a New Element Type</span></a>
      <li><a href="#integrating-a-new-engine-type"><span class="secno">8.2</span> <span class="content">Integrating a New Engine Type</span></a>
      <li><a href="#customizing-an-arithmetic-operation"><span class="secno">8.3</span> <span class="content">Customizing an Arithmetic Operation</span></a>
     </ol>
    <li>
     <a href="#future-directions"><span class="secno">9</span> <span class="content">Future Directions</span></a>
     <ol class="toc">
      <li>
       <a href="#kona-feedback"><span class="secno">9.1</span> <span class="content">Kona Feedback</span></a>
       <ol class="toc">
        <li><a href="#lewg-i-polls-and-feedback-wednesday-2019-02-20"><span class="secno">9.1.1</span> <span class="content">LEWG(I) Polls and Feedback (Wednesday 2019-02-20)</span></a>
        <li><a href="#feedback-from-joint-sg14-sg19-session-friday-2019-02-22"><span class="secno">9.1.2</span> <span class="content">Feedback From Joint SG14/SG19 Session (Friday 2019-02-22)</span></a>
        <li><a href="#other-suggestions-gathered-received-at-kona"><span class="secno">9.1.3</span> <span class="content">Other Suggestions Gathered Received at Kona</span></a>
       </ol>
     </ol>
   </ol>
  </nav>
  <main>
   <h3 class="heading settled" id="revision-history"><span class="content">Revision History</span></h3>
   <table id="t01" style="width: 100%;">
    <tbody>
     <tr>
      <th style="text-align: center;"> Version 
      <th style="text-align: left;"> Description 
     <tr>
      <td style="text-align: center;"> R0 
      <td> Inital version for pre-Kona mailing 
     <tr>
      <td style="text-align: center;"> D1 
      <td> Update for presentation at Kona; includes operator traits, some
      customization examples, and several typo and readability fixes. 
     <tr>
      <td style="text-align: center;"> R1 
      <td> Update for post-Kona mailing; includes feedback from LEWG(I) and joint
      SG14/SG19 session. 
   </table>
   <h2 class="heading settled" data-level="1" id="introduction"><span class="secno">1. </span><span class="content">Introduction</span><a class="self-link" href="#introduction"></a></h2>
   <p>Linear algebra is a mathematical discipline of ever-increasing importance,
with direct application to a wide variety of problem domains, such as signal 
processing, computer graphics, medical imaging, scientific simulations, 
machine learning, analytics, financial modeling, and high-performance 
computing.  And yet, despite the relevance of linear algebra to so many 
aspects of modern computing, the C++ standard library does not include a 
set of linear algebra facilities. This paper proposes to remedy this deficit 
for C++23.</p>
   <p>This paper should be read after P1166, in which we describe a high-level
set of expectations for what a linear algebra library should contain.</p>
   <h2 class="heading settled" data-level="2" id="goals"><span class="secno">2. </span><span class="content">Goals</span><a class="self-link" href="#goals"></a></h2>
   <p>We expect that typical users of a standard linear algebra library are
likely to value two features above all else: ease-of-use (including
expressiveness), and high performance out of the box. This set of users 
will expect the ability to compose arithmetical expressions of linear 
algebra objects similar to what one might find in a textbook; indeed, 
this has been deemed a "must-have" feature by several participants in 
recent SG14 Linear Algebra SIG conference calls. And for a given 
arithmetical expression, they will expect run-time computational 
performance that is close to what they could obtain with an equivalent 
sequence of function calls to a more "traditional" linear algebra library, 
such as <em>LAPCK</em>, <em>Blaze</em>, <em>Eigen</em>, etc.</p>
   <p>There also exists a set of linear algebra “super-users” who will value
most highly a third feature – the ability to customize underlying
infrastructure in order to maximize performance for specific problems
and computing platforms. These users seek the highest possible run-time
performance, and to achieve it, require the ability to customize any and
every portion of the library’s computational infrastructure.</p>
   <p>With these high-level user requirements in mind, in this paper we propose
an interface specification intended to achieve the following goals:</p>
   <ol>
    <li data-md>
     <p>To provide a set of vocabulary types for representing the
mathematical objects and operations that are relevant to linear
algebra;</p>
    <li data-md>
     <p>To provide a public interface for linear algebra operations that is
intuitive, teachable, and mimics the expressiveness of mathematical
notation to the greatest <em>reasonable</em> extent;</p>
    <li data-md>
     <p>To exhibit out-of-the-box performance in the neighborhood of that
of that exhibited by an equivalent sequence of function calls to a more 
traditional linear algebra library, such as <em>LAPACK</em>, <em>Blaze</em>, <em>Eigen</em>, etc.;</p>
    <li data-md>
     <p>To provide a set of building blocks that manage the source,
ownership, lifetime, layout, and access of the memory required to
represent the linear algebra vocabulary types, with the requirement
that some of these building blocks are also suitable for (eventually)
representing other interesting mathematical entities, such as quaternions, 
octonions, and tensors;</p>
    <li data-md>
     <p>To provide straightforward facilities and techniques for
customization that enable users to optimize performance for their
specific problem domain on their specific hardware; and,</p>
    <li data-md>
     <p>To provide a <em>reasonable</em> level of granularity for customization so
that developers only have to implement a minimum set of types and 
functions to integrate their performance enhancements with the rest of
the linear algebra facilities described here.</p>
   </ol>
   <h2 class="heading settled" data-level="3" id="definitions"><span class="secno">3. </span><span class="content">Definitions</span><a class="self-link" href="#definitions"></a></h2>
   <p>When discussing linear algebra and related topics for a proposal such as
this, it is important to note that there are several overloaded terms
(such as <em>matrix</em>, <em>vector</em>, <em>dimension</em>, and <em>rank</em>) which must be
defined and disambiguated if such discussions are to be productive.
These terms have specific meanings in mathematics, as well as different,
but confusingly similar, meanings to C++ programmers.</p>
   <p>In the following sections we provide definitions for relevant
mathematical concepts, C++ type design concepts, and describe how 
this proposal employs those overloaded terms in various contexts.</p>
   <h3 class="heading settled" data-level="3.1" id="mathematical-terms"><span class="secno">3.1. </span><span class="content">Mathematical Terms</span><a class="self-link" href="#mathematical-terms"></a></h3>
   <p>In order to facilitate subsequent discussion, we first provide the
following <em>informal</em> set of definitions for important mathematical
concepts:</p>
   <ol>
    <li data-md>
     <p>A <strong>vector space</strong> is a collection of <strong>vectors</strong>, where vectors
are objects that may be added together and multiplied by scalars.
Euclidean vectors are an example of a vector space, typically used
to represent displacements, as well as physical quantities such as
force or momentum. Linear algebra is concerned primarily with the
study of vector spaces.</p>
    <li data-md>
     <p>The <strong>dimension</strong> of a vector space is the minimum number of
coordinates required to specify any point within the space.</p>
    <li data-md>
     <p>A <strong>matrix</strong> is a rectangular array of numbers, symbols, or
expressions, arranged in rows and columns. A matrix having <em>m</em> rows
and <em>n</em> columns is said to have size <em>m</em> x <em>n</em>. Although matrices
can be used solve systems of simultaneous linear equations, they are
most commonly used to represent linear transformations, solve linear
least squares problems, and to explore and/or manipulate the
properties of vector spaces.</p>
    <li data-md>
     <p>The <strong>rank</strong> of a matrix is the dimension of the vector space
spanned by its columns, which is equal to the dimension of the
vector space spanned by its rows. The rank is also equal to the
maximum number of linearly-independent columns and rows.</p>
    <li data-md>
     <p>An <strong>element</strong> of a matrix is an individual member (number, symbol,
expression) of the rectangular array comprising the matrix, lying at
the intersection of a single row and a single column. In traditional
mathematical notation, row and column indexing is 1-based, where
rows are indexed from 1 to <em>m</em> and columns are indexed from 1 to <em>n</em>. Given some matrix <em>A</em>, element <em>a</em><sub><em>11</em></sub> refers to the
element in the upper left-hand corner of the array and element <em>a</em><sub><em>mn</em></sub> refers to the element in the lower right-hand
corner.</p>
    <li data-md>
     <p>A <strong>row vector</strong> is a matrix containing a single row; in other
words, a matrix of size <em>1</em> x <em>n</em>. In many applications of linear
algebra, row vectors represent spatial vectors.</p>
    <li data-md>
     <p>A <strong>column vector</strong> is a matrix containing a single column; in other
words, a matrix of size <em>m</em> x <em>1</em>. In many applications of linear
algebra, column vectors represent spatial vectors.</p>
    <li data-md>
     <p><strong>Element transforms</strong> are non-arithmetical operations that modify
the relative positions of elements in a matrix, such as transpose,
column exchange, and row exchange.</p>
    <li data-md>
     <p><strong>Element arithmetic</strong> refers to arithmetical operations that read
or modify the values of individual elements independently of other
elements, such assigning a value to a specific element or
multiplying a row by some value.</p>
    <li data-md>
     <p><strong>Matrix arithmetic</strong> refers to the assignment, addition,
subtraction, negation, multiplication, and determinant operations
defined for matrices, row vectors, and column vectors as wholes.</p>
    <li data-md>
     <p>A <strong>rectangular matrix</strong> is a matrix requiring a full <em>m</em> x <em>n</em> representation; that is, a matrix not possessing a special form,
such as identity, triangular, band, etc.</p>
    <li data-md>
     <p>The <strong>identity matrix</strong> is a square matrix where all elements on the
diagonal are equal to one and all off-diagonal elements are equal to
zero.</p>
    <li data-md>
     <p>A <strong>triangular matrix</strong> is a matrix where all elements above or
below the diagonal are zero; those with non-zero elements above the
diagonal are called <em>upper triangular</em>, while those with non-zero
elements below the diagonal are called <em>lower triangular</em>.</p>
    <li data-md>
     <p>A <strong>band matrix</strong> is a sparse matrix whose non-zero entries are
confined to a diagonal band, lying on the main diagonal and zero or
more diagonals on either side.</p>
    <li data-md>
     <p><strong>Decompositions</strong> are complex sequences of arithmetic operations,
element arithmetic, and element transforms performed upon a matrix
that expose important mathematical properties of that matrix.
Several types of decomposition are often performed in solving
least-squares problems.</p>
    <li data-md>
     <p><strong>Eigen-decompositions</strong> are decompositions performed upon a
symmetric matrix in order to compute the eigenvalues and
eigenvectors of that matrix; this is often performed when solving
problems involving linear dynamic systems.</p>
   </ol>
   <h3 class="heading settled" data-level="3.2" id="terms-pertaining-to-c-types"><span class="secno">3.2. </span><span class="content">Terms Pertaining to C++ Types</span><a class="self-link" href="#terms-pertaining-to-c-types"></a></h3>
   <p>The following are terms used in this proposal that describe various
aspects of how the mathematical concepts described above in Section 3.1
might be implemented:</p>
   <ol>
    <li data-md>
     <p>An <strong>array</strong> is a data structure representing an indexable collection
of objects (elements) such that each element is identified by at 
least one index. An array is said to be <em>one-dimensional</em> array if its 
elements are accessible with a single index; a <em>multi-dimensional</em> array 
is an array for which more than one index is required to access its 
elements.</p>
    <li data-md>
     <p>The <strong>dimension</strong> of an array refers to the number of indices
required to access an element of that array. The <strong>rank</strong> of an
array is a synonym for its dimension.</p>
    <li data-md>
     <p>This proposal uses the term <strong>MathObj</strong> to refer generically to one
of the C++ types described herein representing matrices, row
vectors, and column vectors. These are the public-facing facilities
developers will use in their code.</p>
    <li data-md>
     <p>An <strong>engine</strong> is an implementation type that manages the resources
associated with a <em>MathObj</em> instance.  This includes, at a minumum, the 
storage-related aspects of, and access to, the elements of a <em>MathObj</em>. 
It could also include execution-related aspects, such as an execution 
context. In this proposal, an engine object is a private member of a <em>MathObj</em>. Other than as a template parameter, engines are not part of 
a <em>MathObj</em>’s public interface.</p>
    <li data-md>
     <p>The adjective <strong>dense</strong> refers to a <em>MathObj</em> representation where
storage is allocated for every element.</p>
    <li data-md>
     <p>The adjective <strong>sparse</strong> refers to a <em>MathObj</em> representation where
storage is allocated only for non-zero elements;</p>
    <li data-md>
     <p><strong>Storage</strong> is used by this proposal as a synonym for memory.</p>
    <li data-md>
     <p><strong>Traits</strong> refers to a stateless class template that provides some
set of services, normalizing those services over its set of template
parameters.</p>
    <li data-md>
     <p><strong>Row size</strong> and <strong>column size</strong> refer to the number of rows and
columns, respectively, that a <em>MathObj</em> represents, which must be
less than or equal to its row and column capacities, defined below.</p>
    <li data-md>
     <p><strong>Row capacity</strong> and <strong>column capacity</strong> refer to the maximum number
of rows and columns, respectively, that a <em>MathObj</em> can possibly
represent.</p>
    <li data-md>
     <p><strong>Fixed-size</strong> (FS) refers to an engine type whose row and column
sizes are fixed at instantiation time and constant thereafter.</p>
    <li data-md>
     <p><strong>Fixed-capacity</strong> (FC) refers to an engine type whose row and
column capacities are fixed at instantiation time and constant
thereafter.</p>
    <li data-md>
     <p><strong>Dynamically re-sizable</strong> (DR) refers to an engine type whose row
and column sizes and capacities may be changed at run time.</p>
   </ol>
   <h3 class="heading settled" data-level="3.3" id="overloaded-terms"><span class="secno">3.3. </span><span class="content">Overloaded Terms</span><a class="self-link" href="#overloaded-terms"></a></h3>
   <p>This section describes how we use certain overloaded terms in this proposal
and in future works.</p>
   <h4 class="heading settled" data-level="3.3.1" id="matrix"><span class="secno">3.3.1. </span><span class="content">Matrix</span><a class="self-link" href="#matrix"></a></h4>
   <p>The term <em>matrix</em> is frequently used by C++ programmers to mean a
general-purpose array of arbitrary size. For example, one of the authors
worked at a company where it was common practice to refer to 4-dimensional 
arrays as “4-dimensional matrices.”</p>
   <p>In this proposal, we use the word <em>array</em> only to mean a data structure
whose elements are accessible using one or more indices, and which has
no invariants pertaining to higher-level or mathematical meaning.</p>
   <p>We use <em>matrix</em> to mean the mathematical object as defined above in
Section 3.1, and <code class="highlight"><c- n>matrix</c-></code> (in monospaced font) to mean the C++ class
template that implements the mathematical object. We sometimes use <code class="highlight"><c- n>MathObj</c-></code> (in monospaced font) in some of the component interface code
and text below to generically refer to a <code class="highlight"><c- n>matrix</c-></code>, <code class="highlight"><c- n>row_vector</c-></code>, or <code class="highlight"><c- n>column_vector</c-></code> object.</p>
   <h4 class="heading settled" data-level="3.3.2" id="vector"><span class="secno">3.3.2. </span><span class="content">Vector</span><a class="self-link" href="#vector"></a></h4>
   <p>Likewise, many C++ programmers incorrectly use the term <em>vector</em> as a
synonym for “dynamically re-sizable array.” This bad habit is
exacerbated by the unfortunate naming of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code>.</p>
   <p>This proposal uses the term <em>vector</em> to mean an element of a vector
space, per Section 3.1. Further, <em>row vector</em> and <em>column vector</em> have
the meanings set out in 3.1, while <code class="highlight"><c- n>row_vector</c-></code> and <code class="highlight"><c- n>column_vector</c-></code> (in 
monospaced font) are the C++ class templates implementing those mathematical 
objects, respectively. We sometimes use <code class="highlight"><c- n>MathObj</c-></code> (in monospaced font) in
some of the component code interface code and test below to generically 
refer to a <code class="highlight"><c- n>row_vector</c-></code>, <code class="highlight"><c- n>column_vector</c-></code>, or <code class="highlight"><c- n>matrix</c-></code> object.</p>
   <h4 class="heading settled" data-level="3.3.3" id="dimension"><span class="secno">3.3.3. </span><span class="content">Dimension</span><a class="self-link" href="#dimension"></a></h4>
   <p>In linear algebra, a vector space <em>V</em> is said to be of <em>dimension n</em>, or
be <em>n-dimensional</em>, if there exist <em>n</em> linearly independent vectors which
span <em>V</em>. This is another way of saying that <em>n</em> is the minimum number
of coordinates required to specify any point in <em>V</em>. However, in common
programming parlance, <em>dimension</em> refers to the number of indices used
to access an element in an array.</p>
   <p>We use the term dimension both ways in this proposal, but try to do so
consistently and in a way that is clear from the context. For example, a
rotation matix used by a game engine is two-dimensional data structure 
composed of three-dimensional row and column vectors. A vector describing 
an electric field is an example of a one-dimensional data structure that
implemented as a three-dimensional column vector.</p>
   <h4 class="heading settled" data-level="3.3.4" id="rank"><span class="secno">3.3.4. </span><span class="content">Rank</span><a class="self-link" href="#rank"></a></h4>
   <p>The <em>rank</em> of a matrix is the dimension of the vector space spanned by
its columns (or rows), which corresponds to the maximal number of
linearly independent columns (or rows) of that matrix. Rank also has 
another meaning in tensor analysis, where it is commonly used as a
synonym for a tensor’s <em>order</em>.</p>
   <p>However, rank also has a meaning in computer science where it is used as
a synonym for dimension. In the C++ standard at [<em>meta.unary.prop.query</em>], 
rank is described as the number of dimensions of <code class="highlight"><c- n>T</c-></code> if <code class="highlight"><c- n>T</c-></code> names an array, 
otherwise it is zero.</p>
   <p>We avoid using the term <em>rank</em> in this proposal in the context of linear
algebra, except as a quantity that might result from performing certain
decompositions wherein the mathematical rank of a matrix is computed.</p>
   <h2 class="heading settled" data-level="4" id="scope"><span class="secno">4. </span><span class="content">Scope</span><a class="self-link" href="#scope"></a></h2>
   <p>We contend that the best approach for standardizing a set of linear
algebra components for C++23 will be one that is layered, iterative, and
incremental. This paper is quite deliberately a “basic linear algebra-only”
proposal; it describes what we believe is a foundational layer providing
the minimum set of components and arithmetic operations necessary to provide 
a reasonable, basic level of functionality.</p>
   <p>Higher-level functionality can be specified in terms of the interfaces
described here, and we encourage succession papers to explore this
possibility.</p>
   <h3 class="heading settled" data-level="4.1" id="functionality"><span class="secno">4.1. </span><span class="content">Functionality</span><a class="self-link" href="#functionality"></a></h3>
   <p>The foundational layer, as described here, should include the minimal
set of types and functions required to perform matrix arithmetic in
finite dimensional spaces. This includes:</p>
   <ul>
    <li data-md>
     <p>Matrix, row vector, and column vector class templates;</p>
    <li data-md>
     <p>Arithmetic operations for addition, subtraction, negation, and
multiplication of matrices and row/column vectors;</p>
    <li data-md>
     <p>Arithmetic operations for scalar multiplication of matrices and
row/column vectors;</p>
    <li data-md>
     <p>Well-defined facilities for integrating new element types;</p>
    <li data-md>
     <p>Well-defined facilities for creating and integrating custom engines; and,</p>
    <li data-md>
     <p>Well-defined facilities for creating and integrating custom arithmetic
operations.</p>
   </ul>
   <h3 class="heading settled" data-level="4.2" id="considered-but-excluded"><span class="secno">4.2. </span><span class="content">Considered but Excluded</span><a class="self-link" href="#considered-but-excluded"></a></h3>
   <p><strong>Tensors</strong></p>
   <p>There has been a great deal of interest expressed in specifying an
interface for general-purpose tensor processing in which linear algebra
facilities fall out as a special case. We exclude this idea from this
proposal for two reasons. First, given the practical realities of
standardization work, the enormous scope of such an effort would very
likely delay introduction of linear algebra facilities until C++26 or
later.</p>
   <p>Second, and more importantly, implementing matrices as derived types or
specializations of a general-purpose tensor type is bad type design.
Consider the following: a tensor is (informally) an array of
mathematical objects (numbers or functions) such that its elements
transform according to certain rules under a coordinate system change.
In a <em>p</em>-dimensional space, a tensor of rank <em>n</em> will have <em>p</em><sup><em>n</em></sup> elements. In particular, a rank-2 tensor in a <em>p</em>-dimensional space may be represented by a <em>p</em> x <em>p</em> matrix having
certain invariants related to coordinate transformation not possessed by
all <em>p</em> x <em>p</em> matrices.</p>
   <p>These defining characteristics of a tensor lead us to the crux of the
issue: every rank-2 tensor can be represented by a square matrix, but
not every square matrix represents a tensor. As one quickly realizes,
only a small fraction of all possible matrices are representations of
rank-2 tensors.</p>
   <p>All of this is a long way of saying that the class invariants governing
a matrix type are quite different from those governing a tensor type,
and as such, the public interfaces of such types will also differ
substantially.</p>
   <p>From this we conclude that matrices are not Liskov-substitutable for
rank-2 tensors, and therefore as matter of good type design, matrices
and tensors should be implemented as distinct types, perhaps with
appropriate inter-conversion operations.</p>
   <p>This situation is analogous to the age-old object-oriented design
question: when designing a group of classes that represent geometric
shapes, is a square a kind of rectangle? In other words, should class <code class="highlight"><c- n>square</c-></code> be publicly derived from class <code class="highlight"><c- n>rectangle</c-></code>? Mathematically,
yes, a square <em>is</em> a rectangle. But from the perspective of good
interface design, class <code class="highlight"><c- n>square</c-></code> is not substitutable for class <code class="highlight"><c- n>rectangle</c-></code> and is usually best implemented as a distinct type having
no IS-A relationship with <code class="highlight"><c- n>rectangle</c-></code>.</p>
   <p><strong>Quaternions and Octonions</strong></p>
   <p>There has also been interest expressed in including other useful
mathematical objects, such as quaternions and octonions, as part of a
standard linear algebra library. Although element storage for these
types might be implemented using the engines described in this proposal,
quaternions and octonions represent mathematical concepts that are
fundamentally different from those of matrices and vectors.</p>
   <p>As with tensors, the class invariants and public interfaces for
quaternions and octonions would be substantially different from that of
the linear algebra components. Liskov substitutability would not be
possible, and therefore quaternions and octonions should be implemented
as a set of types distinct from the linear algebra types.</p>
   <h2 class="heading settled" data-level="5" id="design-aspects"><span class="secno">5. </span><span class="content">Design Aspects</span><a class="self-link" href="#design-aspects"></a></h2>
   <p>The following describe several important aspects of the problem domain
affecting the design of the proposed interface. Importantly, these
aspects are orthogonal, and are addressable through judicious
combinations of template parameters and implementation type design.</p>
   <h3 class="heading settled" data-level="5.1" id="memory-source"><span class="secno">5.1. </span><span class="content">Memory Source</span><a class="self-link" href="#memory-source"></a></h3>
   <p>Perhaps the first question to be answered is that of the source of
memory in which elements will reside. One can easily imagine multiple
sources of memory:</p>
   <ul>
    <li data-md>
     <p>Elements reside in an external buffer allocated from the global heap.</p>
    <li data-md>
     <p>Elements reside in an external buffer allocated by a custom allocator
and/or specialized heap.</p>
    <li data-md>
     <p>Elements reside in an external fixed-size buffer that exists
independently of the <em>MathObj</em>, not allocated from a heap, and which
has a lifetime greater than that of the <em>MathObj</em>.</p>
    <li data-md>
     <p>Elements reside in a fixed-size buffer that is a member of the <em>MathObj</em> itself.</p>
    <li data-md>
     <p>Elements reside collectively in a set of buffers distributed across
multiple machines.</p>
   </ul>
   <h3 class="heading settled" data-level="5.2" id="addressing-model"><span class="secno">5.2. </span><span class="content">Addressing Model</span><a class="self-link" href="#addressing-model"></a></h3>
   <p>It is also possible that the memory used by a <em>MathObj</em> might be
addressed using what the standard calls a <em>pointer-like type</em>, also
known as a <em>fancy pointer</em>.</p>
   <p>For example, consider an element buffer existing in a shared memory
segment managed by a custom allocator. In this case, the allocator might
employ a fancy pointer type that performs location-independent
addressing based on a segment index and an offset into that segment.</p>
   <p>One can also imagine a fancy pointer that is a handle to a memory
resource existing somewhere on a network, and addressing operations
require first mapping that resource into the local address space,
perhaps by copying over the network or by some magic sequence of RPC
invocations.</p>
   <h3 class="heading settled" data-level="5.3" id="memory-ownership"><span class="secno">5.3. </span><span class="content">Memory Ownership</span><a class="self-link" href="#memory-ownership"></a></h3>
   <p>The next important questions pertain to memory ownership. Should the
memory in which elements reside be deallocated, and if so, what object
is responsible for performing the deallocation?</p>
   <p>A <em>MathObj</em> might own the memory in which it stores its elements, or it
might employ some non-owning view type, like <code class="highlight"><c- n>mdspan</c-></code>, to manipulate
elements owned by some other object.</p>
   <h3 class="heading settled" data-level="5.4" id="capacity-and-resizability"><span class="secno">5.4. </span><span class="content">Capacity and Resizability</span><a class="self-link" href="#capacity-and-resizability"></a></h3>
   <p>As with <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>string</c-></code> and <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>vector</c-></code>, it is occasionally useful
for a <em>MathObj</em> to have excess storage capacity in order to reduce the
number of re-allocations required by anticipated future resizing operations. 
Some linear algebra libraries, like <em>LAPACK</em>, account for the fact that a <em>MathObj</em>’s capacity may be different than its size. This capability was
of critical importance to the success of one author’s prior work in
functional MRI image analysis.</p>
   <p>In other problem domains, like computer graphics, <em>MathObj</em>s are small
and always of the same size. In this case, the size and capacity are
equal, and there is no need for a <em>MathObj</em> to maintain or manage excess
capacity.</p>
   <h3 class="heading settled" data-level="5.5" id="element-layout"><span class="secno">5.5. </span><span class="content">Element Layout</span><a class="self-link" href="#element-layout"></a></h3>
   <p>There are many ways to arrange the elements of a matrix in memory, the
most common in C++ being row-major dense rectangular. In Fortran-based
libraries, the two-dimensional arrays used to represent matrices are
usually column-major. There are also special arrangements of elements
for upper/lower triangular and banded diagonal matrices that are both
row-major and column-major. These arrangements of elements have been
well-known for many years, and libraries like LAPACK in the hands of a
knowledgeable user can use them to implement code that is optimal in
both time and space.</p>
   <h3 class="heading settled" data-level="5.6" id="element-access-and-indexing"><span class="secno">5.6. </span><span class="content">Element Access and Indexing</span><a class="self-link" href="#element-access-and-indexing"></a></h3>
   <p>In keeping with the goal of supporting a natural syntax, and in analogy
with the indexing operations provided by the random-access standard
library containers, it seems reasonable to provide both const and
non-const indexing for reading and writing individual elements.</p>
   <p>However, support for element indexing raises an important question:
should <em>MathObj</em>s employ 1-based indexing or 0-based indexing? 1-based
indexing is the convention used in mathematical notation (and Fortran),
whereas 0-based indexing is “the C++ way.”</p>
   <h3 class="heading settled" data-level="5.7" id="element-type"><span class="secno">5.7. </span><span class="content">Element Type</span><a class="self-link" href="#element-type"></a></h3>
   <p>C++ supports a relatively narrow range of arithmetic types, lacking
direct support for arbitrary precision numbers and fixed-point numbers,
among others. Libraries exist to implement these types, and they should
not be precluded from use in a standard linear algebra library. It is
possible that individual elements of a <em>MathObj</em> may allocate memory,
and therefore an implementation cannot assume that element types have
trivial constructors or destructors.</p>
   <h3 class="heading settled" data-level="5.8" id="mixed-element-type-expressions"><span class="secno">5.8. </span><span class="content">Mixed-Element-Type Expressions</span><a class="self-link" href="#mixed-element-type-expressions"></a></h3>
   <p>In general, when multiple built-in arithmetic types are present in an
arithmetical expression, the resulting type will have a precision
greater than or equal to that of the type with greatest precision in the
expression. In other words, to the greatest reasonable extent, information 
is preserved.</p>
   <p>We contend that a similar principal should apply to expressions involving <em>MathObj</em>s where more than one element type is present. Arithmetic operations
involving <em>MathObj</em>s should, to the greatest reasonable extent, preserve 
element-wise information.</p>
   <p>For example, just as the result of multiplying a <code class="highlight"><c- b>float</c-></code> by a <code class="highlight"><c- b>double</c-></code> is a <code class="highlight"><c- b>double</c-></code>, the result multiplying a matrix-of-<code class="highlight"><c- b>float</c-></code> by a matrix-of-<code class="highlight"><c- b>double</c-></code> should be a matrix-of-<code class="highlight"><c- b>double</c-></code>. We call the
process of determining the resulting element type <em>element promotion</em>.</p>
   <h3 class="heading settled" data-level="5.9" id="mixed-engine-expressions"><span class="secno">5.9. </span><span class="content">Mixed-Engine Expressions</span><a class="self-link" href="#mixed-engine-expressions"></a></h3>
   <p>In analogy with element type, <em>MathObj</em> expressions may include mixed
storage management strategies, as implemented by their corresponding
engine types. For example, consider the case of a fixed-size matrix
multiplied by a dynamically-resizable matrix. What is the engine type of
the resulting matrix?</p>
   <p>Expression involving mixed engine types should not limit the
availability of basic arithmetic operations. This means that there
should be a mechanism for determining the engine type of the resulting
from such expressions. We call the process of determining the resulting
engine type <em>engine promotion</em>.</p>
   <p>We contend that in most cases, the resulting engine type should be at
least as "general" as the most "general" of the two engine types.
For example, one could make the argument that a dynamically-resizable
engine is more general that a fixed-size engine, and therefore an
the resulting engine type in an expression involving both these engine
types should be a dynamically-resizable engine.</p>
   <h3 class="heading settled" data-level="5.10" id="arithmetic-customization"><span class="secno">5.10. </span><span class="content">Arithmetic Customization</span><a class="self-link" href="#arithmetic-customization"></a></h3>
   <p>In pursuit of optimal performance, developers may want to customize
specific arithmetic operations, such as matrix-matrix or matrix-vector
multiplication.  Customization might be based on things like element 
layout in memory, fixed-size -vs- dynamically resizable, special hardware
capabilities, etc.</p>
   <p>One such possible optimization is the use of multiple cores, perhaps
distributed across a network, to carry out multiplication on very large 
pairs of matrices, particularly in situations where the operation is used 
to produce a third matrix rather than modify one of the operands; the 
matrix multiplication operation is particularly amenable to this approach.</p>
   <p>Developers may also wish to make use of SIMD intrinsics to enable
parallel evaluation of matrix multiplication. This is common in game
development environments where programs are written for very specific
platforms, where the make and model of processor is well defined. This
would impact on element layout and storage. Such work has already been
demonstrated in paper N4454.</p>
   <p>It is possible that two operands may be associated with different arithmetic
customizations.  We call the process of determining which of those two 
customizations to employ when performing the actual arithmetic operations <em>operator traits promotion</em>.</p>
   <h3 class="heading settled" data-level="5.11" id="linear-algebra-and-constexpr"><span class="secno">5.11. </span><span class="content">Linear Algebra and <code class="highlight"><c- k>constexpr</c-></code></span><a class="self-link" href="#linear-algebra-and-constexpr"></a></h3>
   <p>The fundamental set of operations for linear algebra can all be
implemented in terms of a subset of the algorithms defined in the <code class="highlight"><c- o>&lt;</c-><c- n>algorithm</c-><c- o>></c-></code> header, all of which are marked <code class="highlight"><c- k>constexpr</c-></code> since
C++20. Matrix and vector initialization is of course also possible at
compile time.</p>
   <p>The arrival of <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_constant_evaluated</c-></code> in C++20 makes it
possible to offer a <code class="highlight"><c- k>constexpr</c-></code> implementation of the operations,
allowing customizations to defer to them in <code class="highlight"><c- k>constexpr</c-></code> evaluations
while taking the customization’s notionally superior run-time path in
alternate situations.</p>
   <h2 class="heading settled" data-level="6" id="interface-design-description"><span class="secno">6. </span><span class="content">Interface Design Description</span><a class="self-link" href="#interface-design-description"></a></h2>
   <p>In this section, we describe the various types, operators, and functions
comprising the proposed interface. The reader should note that the
descriptions below are by no means ready for wording; rather, they are
intended to foster further discussions and refinements, and to serve
as a guide for brave souls attempting to build implementations from this
specification.</p>
   <h3 class="heading settled" data-level="6.1" id="overview"><span class="secno">6.1. </span><span class="content">Overview</span><a class="self-link" href="#overview"></a></h3>
   <p>At the highest level, the interface is divided into three broad categories:</p>
   <ol>
    <li data-md>
     <p><strong>MathObjs</strong>, each of which provides an interface intended to model a
corresponding mathematical abstraction (column vector, row vector, matrix);</p>
    <li data-md>
     <p><strong>Engines</strong>, which are implementation types that manage the resources
associated with a <em>MothObj</em> instance; and,</p>
    <li data-md>
     <p><strong>Operators</strong>, which provide the desired mathematical syntax and carry
out the promised arithmetic.</p>
   </ol>
   <p>At a lower level, and behind the scenes, are a number of supporting
traits types employed by the operators to determine the return type of 
the operator and perform the corresponding arithmetic operation.  There 
are several such traits types, which are intended to act as customization
points:</p>
   <ul>
    <li data-md>
     <p><strong>Element promotion helper traits</strong> determine whether or not a given
type <code class="highlight"><c- n>T</c-></code> is an acceptable <em>MathObj</em> element type.</p>
    <li data-md>
     <p><strong>Element promotion traits</strong> determine the resulting element type for
an arithmetical operation based on two the element types of two input 
operands. This traits type uses the element promotion helper traits to 
verify that both input types are in fact acceptable matrix element types.</p>
    <li data-md>
     <p><strong>Engine promotion traits</strong> determine the type of an engine resulting
from an arithemtical operation.  As part of that process, this traits
type uses the element promotion traits to determine the element type of 
the resulting engine.</p>
    <li data-md>
     <p><strong>Arithmetic traits</strong> determine the type of a <em>MathObj</em> resulting
from an arithmetical operation.  As part of that process, this traits
type uses the engine promotion traits to determine the engine type of
the resulting <em>MathObj</em>.  Having determined the result type, the
arithmetic traits also have a member function that carries ot the 
actual computations.</p>
    <li data-md>
     <p><strong>Operator traits</strong> specify a collection of four specific arithmetic
traits types, one type for each supported arithmetic operation.  This 
traits type is a template parameter to the <em>MathObj</em> types, and provides 
a way to inform an operator of the set of suggested arithmetic traits to 
be used when deciding how to perform an arithmetic operation.</p>
    <li data-md>
     <p><strong>Operator promotion traits</strong> provide the means by which an operator
selects the operator traits that will performg the arithmetic.  In the
case where each operand has the same operator traits, the decision is
simple.  However, it is possible that the operands may be instantiated
with different operator traits types, and in this case, the operator
must decide with operator traits type to use in computing its result.</p>
   </ul>
   <p>The following sections describe the building blocks in more detail,
starting at the lowest level, and working upward in order of dependency.</p>
   <h3 class="heading settled" data-level="6.2" id="element-promotion-helper-traits"><span class="secno">6.2. </span><span class="content">Element Promotion Helper Traits</span><a class="self-link" href="#element-promotion-helper-traits"></a></h3>
   <p>Traits type <code class="highlight"><c- n>is_complex</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> determines whether its template paramater <code class="highlight"><c- n>T</c-></code> is of type <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- n>V</c-><c- o>></c-></code> for some type <code class="highlight"><c- n>V</c-></code>, where <code class="highlight"><c- n>V</c-></code> must itself be 
an arithmetical type as determined by <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>is_arithmetic_v</c-><c- o>&lt;</c-><c- n>U</c-><c- o>></c-></code>. Defining 
what constitutes an arithmetic type can be challenging; our intention is 
that an arithmetic type is one that models a field, although types that 
model rings should work as well.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->  <c- k>struct</c-> <c- n>is_complex</c-><c- p>;</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->  <c- k>constexpr</c-> <c- b>bool</c-> <c- n>is_complex_v</c-> <c- o>=</c-> <c- p>...;</c->
</pre>
   <p>Traits type <code class="highlight"><c- n>is_matrix_element</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> is used in static assertions to
ensure that <em>MathObj</em> types are instantiated only with element types
representing a field or ring (i.e., arithmetic types, or complex types 
per above). It uses <code class="highlight"><c- n>is_complex</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> as appropriate to help make that 
determination.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->  <c- k>struct</c-> <c- n>is_matrix_element</c-><c- p>;</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- o>></c->  <c- k>constexpr</c-> <c- b>bool</c-> <c- n>is_matrix_element_v</c-> <c- o>=</c-> <c- p>...;</c->
</pre>
   <h3 class="heading settled" data-level="6.3" id="element-promotion-traits"><span class="secno">6.3. </span><span class="content">Element Promotion Traits</span><a class="self-link" href="#element-promotion-traits"></a></h3>
   <p>Element promotion traits are used by the engine promotion traits to
determine the resulting element type in an binary expression involving 
engines with possibly two different element types.</p>
   <p>Class template <code class="highlight"><c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-></code> implements a traits
type that determines the appropriate result type of an arithmetical
operation involving two (possibly different) <em>MathObj</em> element types.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_element_promotion</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>type</c-> <c- o>=</c-> <c- p>...;</c->           <c- c1>//- Implementation-defined</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- n>T2</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- n>T1</c-><c- o>></c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- n>T1</c-><c- o>></c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- n>T2</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>using</c-> <c- n>matrix_element_promotion_t</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>>::</c-><c- n>type</c-><c- p>;</c->
</pre>
   <p>Note the partial specializations involving <code class="highlight"><c- n>complex</c-><c- o>&lt;</c-><c- n>T</c-><c- o>></c-></code> elements.  Also, as
will be common practice for most of the traits types in this proposal, a
parameterized alias for the trait is also defined.</p>
   <h3 class="heading settled" data-level="6.4" id="engine-types"><span class="secno">6.4. </span><span class="content">Engine Types</span><a class="self-link" href="#engine-types"></a></h3>
   <p>The over-arching purpose of the engine types is to perform resource
management on behalf of an associated <em>MathObj</em> instance.  At a minimum,
all of the engine types provide a basic interface for const element
indexing, row and column sizes, and row and column capacities. They also
export public type aliases which specify their element type, whether or 
not they are dense, whether or not they are rectangular, whether or not 
they are resizable, whether or not their memory layout is row-major, and 
a 2-tuple for describing sizes and capacities.</p>
   <p>One can imagine engines that also manage resources related to execution.</p>
   <h4 class="heading settled" data-level="6.4.1" id="fixed-size-engine"><span class="secno">6.4.1. </span><span class="content">Fixed-Size Engine</span><a class="self-link" href="#fixed-size-engine"></a></h4>
   <p>Class template <code class="highlight"><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-></code> implements a fixed-size,
fixed-capacity engine. In addition to the basic engine interface, it 
provides member functions for mutable element indexing and swapping 
rows and/or columns.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- o>></c->
<c- k>class</c-> <c- nc>fs_matrix_engine</c->
<c- p>{</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Rows</c-> <c- o>>=</c-> <c- mi>1</c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Cols</c-> <c- o>>=</c-> <c- mi>1</c-><c- p>);</c->

  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- n>T</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>false_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_row_major</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>size_t</c-><c- p>,</c-> <c- b>size_t</c-><c- o>></c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
    <c- n>fs_matrix_engine</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine</c-><c- p>(</c-><c- n>fs_matrix_engine</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine</c-><c- p>(</c-><c- n>fs_matrix_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->

    <c- n>fs_matrix_engine</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>fs_matrix_engine</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>fs_matrix_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->

    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c-> <c- k>const</c-><c- o>*</c->    <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>);</c->
    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- n>T</c-><c- o>*</c->      <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>void</c->    <c- nf>swap_columns</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>swap_rows</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>T</c->       <c- n>ma_elems</c-><c- p>[</c-><c- n>Rows</c-><c- o>*</c-><c- n>Cols</c-><c- p>];</c->    <c- c1>//- For exposition; data buffer</c->
<c- p>};</c->
</pre>
   <h4 class="heading settled" data-level="6.4.2" id="dynamically-resizable-engine"><span class="secno">6.4.2. </span><span class="content">Dynamically-Resizable Engine</span><a class="self-link" href="#dynamically-resizable-engine"></a></h4>
   <p>Class template <code class="highlight"><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Alloc</c-><c- o>></c-></code> implements an engine whose
sizes and capacities can be changed at runtime. In addition to the basic
engine interface, it provides member functions for mutable element
indexing, changing size and capacity, and swapping rows and/or columns.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Alloc</c-><c- o>=</c-><c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>class</c-> <c- nc>dr_matrix_engine</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- n>T</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_row_major</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>size_t</c-><c- p>,</c-> <c- b>size_t</c-><c- o>></c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
    <c- n>dr_matrix_engine</c-><c- p>();</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- n>dr_matrix_engine</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- n>dr_matrix_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>,</c-> <c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- n>dr_matrix_engine</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>dr_matrix_engine</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- n>dr_matrix_engine</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>dr_matrix_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>);</c->

    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c-> <c- k>const</c-><c- o>*</c->    <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>);</c->
    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- n>T</c-><c- o>*</c->      <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>void</c->    <c- nf>reserve</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>reserve</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- b>void</c->    <c- nf>resize</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>resize</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>,</c-> <c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- b>void</c->    <c- nf>swap_columns</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>swap_rows</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>using</c-> <c- n>pointer</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator_traits</c-><c- o>&lt;</c-><c- n>Alloc</c-><c- o>>::</c-><c- n>pointer</c-><c- p>;</c->

    <c- n>pointer</c->     <c- n>mp_elems</c-><c- p>;</c->       <c- c1>//- For exposition; data buffer</c->
    <c- b>size_t</c->      <c- n>m_rows</c-><c- p>;</c->
    <c- b>size_t</c->      <c- n>m_cols</c-><c- p>;</c->
    <c- b>size_t</c->      <c- n>m_rowcap</c-><c- p>;</c->
    <c- b>size_t</c->      <c- n>m_colcap</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <h4 class="heading settled" data-level="6.4.3" id="transpose-engine"><span class="secno">6.4.3. </span><span class="content">Transpose Engine</span><a class="self-link" href="#transpose-engine"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_transpose_engine</c-><c- o>&lt;</c-><c- n>Eng</c-><c- o>></c-></code> implements a non-owning,
const view type that provides the basic engine interface.  Its primary 
anticipated use case is as the return value of the <code class="highlight"><c- n>t</c-><c- p>()</c-></code> member function 
of the <em>MathObj</em> types.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng</c-><c- o>></c->
<c- k>class</c-> <c- nc>matrix_transpose_engine</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>engine_type</c->    <c- o>=</c-> <c- n>Eng</c-><c- p>;</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_dense</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_rectangular</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>false_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_row_major</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- o>::</c-><c- n>is_row_major</c-><c- o>::</c-><c- n>value</c-><c- p>,</c-> 
                                                  <c- n>std</c-><c- o>::</c-><c- n>false_type</c-><c- p>,</c->
                                                  <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>size_tuple</c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
    <c- n>matrix_transpose_engine</c-><c- p>();</c->
    <c- n>matrix_transpose_engine</c-><c- p>(</c-><c- n>engine_type</c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>eng</c-><c- p>);</c->
    <c- n>matrix_transpose_engine</c-><c- p>(</c-><c- n>matrix_transpose_engine</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- n>matrix_transpose_engine</c-><c- p>(</c-><c- n>matrix_transpose_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>);</c->

    <c- n>matrix_transpose_engine</c-><c- o>&amp;</c->    <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>matrix_transpose_engine</c-><c- o>&amp;&amp;</c-><c- p>);</c->
    <c- n>matrix_transpose_engine</c-><c- o>&amp;</c->    <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>matrix_transpose_engine</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>);</c->

    <c- n>element_type</c->        <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>element_type</c->        <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>element_type</c-> <c- k>const</c-><c- o>*</c-> <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>engine_type</c-><c- o>*</c->    <c- n>mp_other</c-><c- p>;</c->   <c- c1>//- For exposition; pointer to actual engine</c->
<c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="6.5" id="engine-promotion-traits"><span class="secno">6.5. </span><span class="content">Engine Promotion Traits</span><a class="self-link" href="#engine-promotion-traits"></a></h3>
   <p>Engine promotion traits are used by the arithmetic traits to determine
the resulting engine types in an arithmetical expression.</p>
   <h4 class="heading settled" data-level="6.5.1" id="for-negation"><span class="secno">6.5.1. </span><span class="content">For Negation</span><a class="self-link" href="#for-negation"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_engine_negate_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>></c-></code> implements a traits
type that determines the resulting engine type when negating a <em>MathObj</em>.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_engine_negate_promotion</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- p>...;</c->    <c- c1>//- Implementation-defined</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- o>></c->
<c- k>using</c-> <c- n>matrix_engine_negate_t</c-> <c- o>=</c-> 
    <c- k>typename</c-> <c- n>matrix_engine_negate_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>>::</c-><c- n>engine_type</c-><c- p>;</c->
</pre>
   <h4 class="heading settled" data-level="6.5.2" id="for-addition"><span class="secno">6.5.2. </span><span class="content">For Addition</span><a class="self-link" href="#for-addition"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_engine_add_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-></code> implements a
traits type that determines the resulting engine type when adding two
compatible <em>MathObj</em>s.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_engine_add_promotion</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- p>...;</c->    <c- c1>//- Implementation-defined</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>using</c-> <c- n>matrix_engine_add_t</c-> <c- o>=</c-> 
    <c- k>typename</c-> <c- n>matrix_engine_add_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>>::</c-><c- n>engine_type</c-><c- p>;</c->
</pre>
   <h4 class="heading settled" data-level="6.5.3" id="for-subtraction"><span class="secno">6.5.3. </span><span class="content">For Subtraction</span><a class="self-link" href="#for-subtraction"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_engine_subtract_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-></code> implements a
traits type that determines the resulting engine type when subtracting 
two compatible <em>MathObj</em>s.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_engine_subtract_promotion</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- p>...;</c->    <c- c1>//- Implementation-defined</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>using</c-> <c- n>matrix_engine_subtract_t</c-> <c- o>=</c-> 
    <c- k>typename</c-> <c- n>matrix_engine_subtract_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>>::</c-><c- n>engine_type</c-><c- p>;</c->
</pre>
   <h4 class="heading settled" data-level="6.5.4" id="for-multiplication"><span class="secno">6.5.4. </span><span class="content">For Multiplication</span><a class="self-link" href="#for-multiplication"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_engine_multiply_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-></code> implements a
traits type that determines the resulting engine type when multiplying two 
compatible <em>MathObj</em>s.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_engine_multiply_promotion</c-><c- p>;</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- p>...;</c->    <c- c1>//- Implementation-defined</c->
<c- p>};</c->

<c- c1>//- A possible partial specialization</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Alloc2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_engine_promotion</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>,</c-> 
                                              <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Alloc2</c-><c- o>>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>alloc_type</c->   <c- o>=</c-> 
        <c- k>typename</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator_traits</c-><c- o>&lt;</c-><c- n>Alloc2</c-><c- o>>::</c-><c- k>template</c-> <c- n>rebind_alloc</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c->  <c- o>=</c-> <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>element_type</c-><c- p>,</c-> <c- n>alloc_type</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>using</c-> <c- n>matrix_engine_multiply_t</c-> <c- o>=</c-> 
    <c- k>typename</c-> <c- n>matrix_engine_multiply_promotion</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>>::</c-><c- n>engine_type</c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="6.6" id="mathematical-types"><span class="secno">6.6. </span><span class="content">Mathematical Types</span><a class="self-link" href="#mathematical-types"></a></h3>
   <p>This section describes the three main linear algebra object types proposed
herein: the class templates <code class="highlight"><c- n>column_vector</c-></code>, <code class="highlight"><c- n>row_vector</c-></code>, and <code class="highlight"><c- n>matrix</c-></code>.
The purpose of these types is to model the corresponding mathematical 
concepts, manage underlying implemetations through their engine type 
template parameter, and provide interfaces which can be employed by
overloaded arithmetic operators.</p>
   <h4 class="heading settled" data-level="6.6.1" id="helper-traits"><span class="secno">6.6.1. </span><span class="content">Helper Traits</span><a class="self-link" href="#helper-traits"></a></h4>
   <p>Alias template <code class="highlight"><c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-></code> is a helper used
by the <em>MathObj</em> types to manipulate overload resolution sets for member
functions that perform dynamic storage management.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
<c- k>using</c-> <c- n>enable_if_resizable_t</c-> <c- o>=</c->
    <c- k>typename</c-> <c- n>std</c-><c- o>::</c-><c- n>enable_if_t</c-><c- o>&lt;</c-><c- n>is_same_v</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>&amp;&amp;</c-> <c- n>Eng1</c-><c- o>::</c-><c- n>is_resizable_type</c-><c- o>::</c-><c- n>value</c-><c- p>,</c-> <c- b>bool</c-><c- o>></c-><c- p>;</c->
</pre>
   <h4 class="heading settled" data-level="6.6.2" id="column-vector"><span class="secno">6.6.2. </span><span class="content">Column Vector</span><a class="self-link" href="#column-vector"></a></h4>
   <p>Class template <code class="highlight"><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraits</c-><c- o>></c-></code> represents a column vector, with
element type and resource management implemented by the engine type <code class="highlight"><c- n>Eng</c-></code>, 
and arithmetic operations specified by the operator traits type <code class="highlight"><c- n>OpTraits</c-></code>.  
If the underlying engine type provides dynamic resizing, then this class will 
as well.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits</c-><c- o>></c->
<c- k>class</c-> <c- nc>column_vector</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>engine_type</c->    <c- o>=</c-> <c- n>Eng</c-><c- p>;</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_dense</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_rectangular</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_resizable</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>size_tuple</c-><c- p>;</c->
    <c- k>using</c-> <c- n>transpose_type</c-> <c- o>=</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>matrix_transpose_engine</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>hermitian_type</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>is_complex_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>transpose_type</c-><c- o>></c-><c- p>;</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>is_matrix_element_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>);</c->

  <c- k>public</c-><c- o>:</c->
    <c- o>~</c-><c- n>column_vector</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>column_vector</c-><c- p>();</c->
    <c- n>column_vector</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>column_vector</c-><c- p>(</c-><c- n>column_vector</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>column_vector</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>src</c-><c- p>);</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>column_vector</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>column_vector</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>);</c->

    <c- n>column_vector</c-><c- o>&amp;</c->  <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>column_vector</c-><c- o>&amp;</c->  <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>column_vector</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>column_vector</c-><c- o>&amp;</c->  <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>);</c->

    <c- c1>//- Const element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c->        <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>element_type</c-> <c- k>const</c-><c- o>*</c-> <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Accessors.</c->
    <c- c1>//</c->
    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Transpose and Hermitian.</c->
    <c- c1>//</c->
    <c- n>transpose_type</c->  <c- nf>t</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
    <c- n>hermitian_type</c->  <c- nf>h</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->

    <c- c1>//- Mutable element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>);</c->
    <c- n>element_type</c-><c- o>*</c->   <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Change capacity.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>reserve</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rowcap</c-><c- p>);</c->

    <c- c1>//- Change size.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>);</c->

    <c- c1>//- Change size and capacity in one shot.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>);</c->

    <c- c1>//- Row operations.</c->
    <c- c1>//</c->
    <c- b>void</c->    <c- nf>swap_rows</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c-> <c- k>friend</c-> <c- k>class</c-> <c- nc>row_vector</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>engine_type</c->     <c- n>m_engine</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>column_vector</c-><c- p>(</c-><c- n>engine_type</c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>eng</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <h4 class="heading settled" data-level="6.6.3" id="row-vector"><span class="secno">6.6.3. </span><span class="content">Row Vector</span><a class="self-link" href="#row-vector"></a></h4>
   <p>Class template <code class="highlight"><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraits</c-><c- o>></c-></code> represents a row vector, with
element type and resource management implemented by the engine type <code class="highlight"><c- n>Eng</c-></code>, 
and arithmetic operations specified by the operator traits type <code class="highlight"><c- n>OpTraits</c-></code>.  
If the underlying engine type provides dynamic resizing, then this class 
will as well.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits</c-><c- o>></c->
<c- k>class</c-> <c- nc>row_vector</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>engine_type</c->    <c- o>=</c-> <c- n>Eng</c-><c- p>;</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_dense</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_rectangular</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_resizable</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>size_tuple</c-><c- p>;</c->
    <c- k>using</c-> <c- n>transpose_type</c-> <c- o>=</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>matrix_transpose_engine</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>hermitian_type</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>is_complex_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>transpose_type</c-><c- o>></c-><c- p>;</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>is_matrix_element_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>);</c->

  <c- k>public</c-><c- o>:</c->
    <c- o>~</c-><c- n>row_vector</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>row_vector</c-><c- p>();</c->
    <c- n>row_vector</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>row_vector</c-><c- p>(</c-><c- n>row_vector</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>row_vector</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>src</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- o>></c->
    <c- n>row_vector</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>matrix_transpose_engine</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- o>>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>src</c-><c- p>);</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>row_vector</c-><c- p>(</c-><c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>row_vector</c-><c- p>(</c-><c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- n>row_vector</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>row_vector</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>row_vector</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>row_vector</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>);</c->

    <c- c1>//- Const element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c->        <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>element_type</c-> <c- k>const</c-><c- o>*</c-> <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Accessors.</c->
    <c- c1>//</c->
    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Transpose and Hermitian.</c->
    <c- c1>//</c->
    <c- n>transpose_type</c->  <c- nf>t</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
    <c- n>hermitian_type</c->  <c- nf>h</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->

    <c- c1>//- Mutable element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>);</c->
    <c- n>element_type</c-><c- o>*</c->   <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Change capacity.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>reserve</c-><c- p>(</c-><c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- c1>//- Change size.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->

    <c- c1>//- Change size and capacity in one shot.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- c1>//- column operations.</c->
    <c- c1>//</c->
    <c- b>void</c->    <c- nf>swap_columns</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c-> <c- k>friend</c-> <c- k>class</c-> <c- nc>column_vector</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>engine_type</c->     <c- n>m_engine</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>row_vector</c-><c- p>(</c-><c- n>engine_type</c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>eng</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <h4 class="heading settled" data-level="6.6.4" id="matrix①"><span class="secno">6.6.4. </span><span class="content">Matrix</span><a class="self-link" href="#matrix①"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraits</c-><c- o>></c-></code> represents a matrix, with element type
and resource management implemented by the engine type <code class="highlight"><c- n>Eng</c-></code>, and arithmetic 
operations specified by the operator traits type <code class="highlight"><c- n>OpTraits</c-></code>.  If the underlying 
engine type provides dynamic resizing, then this class will as well.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits</c-><c- o>></c->
<c- k>class</c-> <c- nc>matrix</c->
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>engine_type</c->    <c- o>=</c-> <c- n>Eng</c-><c- p>;</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_dense</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_rectangular</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>is_resizable</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- k>typename</c-> <c- n>engine_type</c-><c- o>::</c-><c- n>size_tuple</c-><c- p>;</c->
    <c- k>using</c-> <c- n>transpose_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>matrix_transpose_engine</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>hermitian_type</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>conditional_t</c-><c- o>&lt;</c-><c- n>is_complex_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c->
                                                  <c- n>transpose_type</c-><c- o>></c-><c- p>;</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>is_matrix_element_v</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>);</c->

  <c- k>public</c-><c- o>:</c->
    <c- o>~</c-><c- n>matrix</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>matrix</c-><c- p>();</c->
    <c- n>matrix</c-><c- p>(</c-><c- n>matrix</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>matrix</c-><c- p>(</c-><c- n>matrix</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>matrix</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>src</c-><c- p>);</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>matrix</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>matrix</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>matrix</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>,</c-> <c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- n>matrix</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- n>matrix</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>matrix</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>matrix</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>matrix</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
    <c- n>matrix</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rhs</c-><c- p>);</c->

    <c- c1>//- Const element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c->        <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>element_type</c-> <c- k>const</c-><c- o>*</c-> <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Accessors.</c->
    <c- c1>//</c->
    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Transpose and Hermitian.</c->
    <c- c1>//</c->
    <c- n>transpose_type</c->  <c- nf>t</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
    <c- n>hermitian_type</c->  <c- nf>h</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->

    <c- c1>//- Mutable element access.</c->
    <c- c1>//</c->
    <c- n>element_type</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- n>element_type</c-><c- o>*</c->   <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- c1>//- Change capacity.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>reserve</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>reserve</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- c1>//- Change size.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>);</c->

    <c- c1>//- Change size and capacity in one shot.</c->
    <c- c1>//</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- n>size_tuple</c-> <c- n>size</c-><c- p>,</c-> <c- n>size_tuple</c-> <c- n>cap</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-> <c- o>=</c-> <c- n>Eng</c-><c- p>,</c-> <c- n>enable_if_resizable_t</c-><c- o>&lt;</c-><c- n>Eng</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-> <c- o>=</c-> true<c- o>></c->
    <c- b>void</c->    <c- n>resize</c-><c- p>(</c-><c- b>size_t</c-> <c- n>rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>cols</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>rowcap</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>colcap</c-><c- p>);</c->

    <c- c1>//- Row and column operations.</c->
    <c- c1>//</c->
    <c- b>void</c->    <c- nf>swap_columns</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>swap_rows</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c-> <c- k>friend</c-> <c- k>class</c-> <c- nc>matrix</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>engine_type</c->     <c- n>m_engine</c-><c- p>;</c->

  <c- k>private</c-><c- o>:</c->
    <c- n>matrix</c-><c- p>(</c-><c- n>engine_type</c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>eng</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="6.7" id="matrix-arithmetic-traits"><span class="secno">6.7. </span><span class="content">Matrix Arithmetic Traits</span><a class="self-link" href="#matrix-arithmetic-traits"></a></h3>
   <p>This section defines a set of arithmetic traits types for negation,
addition, subtraction, and multiplication. The purpose of these traits 
types is threefold:</p>
   <ol>
    <li data-md>
     <p>to determine the element type of the resulting <em>MathObj</em>;</p>
    <li data-md>
     <p>to determine the engine type of the resulting <em>MathObj</em>; and</p>
    <li data-md>
     <p>to carry out the arithmetical operation.</p>
   </ol>
   <p>The idea here is that arithmetic operators (described below) simply forward
to the appropriate traits type, which does the heavy lifting.</p>
   <h4 class="heading settled" data-level="6.7.1" id="negation-traits"><span class="secno">6.7.1. </span><span class="content">Negation Traits</span><a class="self-link" href="#negation-traits"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_negation_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-></code> is an arithmetic
traits type that performs the negation of a <em>MathObj</em> and returns the result 
in another <em>MathObj</em> having an implementation-defined engine type. There 
are three partial specializations to support the three overloaded unary 
negation operators described below.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c-> 
<c- k>struct</c-> <c- n>matrix_negation_traits</c-><c- p>;</c->

<c- c1>//- A possible partial specialization</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_negation_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_negation_engine_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>negate</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>);</c->
<c- p>};</c->

<c- c1>//- Other partial specializations</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_negation_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_negation_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->
</pre>
   <h4 class="heading settled" data-level="6.7.2" id="addition-traits"><span class="secno">6.7.2. </span><span class="content">Addition Traits</span><a class="self-link" href="#addition-traits"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-></code> is an
arithmetic traits type that performs the addition of two compatible <em>MathObj</em>s and returns the result in a <em>MathObj</em> having an 
implementation-defined engine type.  There are three partial specializations 
to support the three overloaded binary addition operators described below.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c-> 
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- p>;</c->

<c- c1>//- A possible partial specialization</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_addition_engine_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>add</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                            <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->

<c- c1>//- Other partial specializations</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->
</pre>
   <h4 class="heading settled" data-level="6.7.3" id="subtraction-traits"><span class="secno">6.7.3. </span><span class="content">Subtraction Traits</span><a class="self-link" href="#subtraction-traits"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_subtraction_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-></code> is an
arithmetic traits type that performs the subtraction of two compatible <em>MathObj</em>s and returns the result in a <em>MathObj</em> having an 
implementation-defined engine type. There are three partial specializations 
to support the three overloaded binary subtraction operators described below.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c-> 
<c- k>struct</c-> <c- n>matrix_subtraction_traits</c-><c- p>;</c->

<c- c1>//- A possible partial specialization</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_subtraction_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_subtraction_engine_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>subtract</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                                 <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->

<c- c1>//- Other partial specializations</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_subtraction_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_subtraction_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                 <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->
</pre>
   <h4 class="heading settled" data-level="6.7.4" id="multiplication-traits"><span class="secno">6.7.4. </span><span class="content">Multiplication Traits</span><a class="self-link" href="#multiplication-traits"></a></h4>
   <p>Class template <code class="highlight"><c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-></code> is an
arithmetic traits type that performs the multiplication of two compatible <em>MathObj</em>s and returns the result in a <em>MathObj</em> having an 
implementation-defined engine type.  Note that there are thirteen partial 
specializations to support the thirteen overloaded binary multiplication 
operators described below.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c-> 
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- p>;</c->

<c- c1>//- A possible partial specialization</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_multiplication_engine_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>multiply</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                                 <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->

<c- c1>//- Other partial specializations</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>T2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>T2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> <c- n>T2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c-> 
<c- p>{...};</c->
</pre>
   <p>One of the partial specializations bears special mention, and that is the
one  corresponding to the inner product.  In this particular case, the 
return value from <code class="highlight"><c- n>multiply</c-><c- p>()</c-></code> is not a <em>MathObj</em>, but instead a promoted
element type:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>elem_type_1</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>elem_type_2</c-> <c- o>=</c-> <c- k>typename</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>>::</c-><c- n>element_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- b>void</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>elem_type_1</c-><c- p>,</c-> <c- n>elem_type_2</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>multiply</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> 
                                 <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="6.8" id="operator-traits"><span class="secno">6.8. </span><span class="content">Operator Traits</span><a class="self-link" href="#operator-traits"></a></h3>
   <p>Class <code class="highlight"><c- n>default_matrix_operator_traits</c-></code> is a traits-style template parameter to <code class="highlight"><c- n>column_vector</c-></code>, <code class="highlight"><c- n>row_vector</c-></code>, and <code class="highlight"><c- n>matrix</c-></code>.  Its purpose is to convey a
suggested set of arithmetical operations to be associated with a given <code class="highlight"><c- n>MathObj</c-></code>.</p>
<pre class="highlight"><c- k>struct</c-> <c- n>default_matrix_operator_traits</c->
<c- p>{</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
    <c- k>using</c-> <c- n>negation_traits</c-> <c- o>=</c-> <c- n>matrix_negation_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>;</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
    <c- k>using</c-> <c- n>addition_traits</c-> <c- o>=</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>;</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
    <c- k>using</c-> <c- n>subtraction_traits</c-> <c- o>=</c-> <c- n>matrix_subtraction_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>;</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Opnd1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Opnd2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
    <c- k>using</c-> <c- n>multiplication_traits</c-> <c- o>=</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>Opnd1</c-><c- p>,</c-> <c- n>Opnd2</c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="6.9" id="operator-traits-promotion"><span class="secno">6.9. </span><span class="content">Operator Traits Promotion</span><a class="self-link" href="#operator-traits-promotion"></a></h3>
   <p>Class template <code class="highlight"><c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-></code> is used by the
arithmetic operators to select a specific arithmetic traits type that will
be used to perform an operation.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_operator_traits_promotion</c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T1</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>traits_type</c-> <c- o>=</c-> <c- n>T1</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>traits_type</c-> <c- o>=</c-> <c- n>T1</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>default_matrix_operator_traits</c-><c- p>,</c-> <c- n>T1</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>traits_type</c-> <c- o>=</c-> <c- n>T1</c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>default_matrix_operator_traits</c-><c- p>,</c->
                                        <c- n>default_matrix_operator_traits</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>traits_type</c-> <c- o>=</c-> <c- n>default_matrix_operator_traits</c-><c- p>;</c->
<c- p>};</c->
</pre>
   <h3 class="heading settled" data-level="6.10" id="arithmetic-operators"><span class="secno">6.10. </span><span class="content">Arithmetic Operators</span><a class="self-link" href="#arithmetic-operators"></a></h3>
   <p>The arithmetic operators provide syntax that mimics common mathematical
notation, with computation executed by an arithmetic traits type 
specified by at least one of the operands' template parameters.</p>
   <p>Readers will note that the return types of the overloaded operators
described below are left unspecified.  This is a deliberate choice so
that implementers have the freedom to choose whatever default technique
for evaluationg expressions they desire; for example, by returning 
temporary objects, or by using expression templates, or perhaps by 
some other technique.</p>
   <h4 class="heading settled" data-level="6.10.1" id="negation-operator"><span class="secno">6.10.1. </span><span class="content">Negation Operator</span><a class="self-link" href="#negation-operator"></a></h4>
   <p>Three overloaded unary negation operators are provided to perform
element-wise negation of a <em>MathObj</em> instance.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>);</c->
</pre>
   <p>Note that this function template is equivalent to multiplying the
argument by the scalar value of <code class="highlight"><c- k>static_cast</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>></c-><c- p>(</c-><c- o>-</c-><c- mi>1</c-><c- p>)</c-></code>.</p>
   <h4 class="heading settled" data-level="6.10.2" id="addition-operator"><span class="secno">6.10.2. </span><span class="content">Addition Operator</span><a class="self-link" href="#addition-operator"></a></h4>
   <p>Three overloaded binary addition operators are provided to perform
element-wise addition of two <em>MathObj</em> instances.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>+</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> 
                   <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>+</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> 
                   <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>+</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                   <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
</pre>
   <p>Specifically, this operator performs the addition of two <code class="highlight"><c- n>MathObj</c-></code> instances of identical dimension.</p>
   <h4 class="heading settled" data-level="6.10.3" id="subtraction-operator"><span class="secno">6.10.3. </span><span class="content">Subtraction Operator</span><a class="self-link" href="#subtraction-operator"></a></h4>
   <p>Three overloaded binary subtraction operators are provided to perform
element-wise subtraction of two <em>MathObj</em> instances.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> 
                   <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> 
                   <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>-</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                   <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
</pre>
   <p>Specifically, this operator performs the subtraction of two <code class="highlight"><c- n>MathObj</c-></code> instances of identical dimension.</p>
   <h4 class="heading settled" data-level="6.10.4" id="multiplication-operator"><span class="secno">6.10.4. </span><span class="content">Multiplication Operator</span><a class="self-link" href="#multiplication-operator"></a></h4>
   <p>Thirteen overloaded binary multiplication operators are provided to
perform appropriate multiplication of two <em>MathObj</em> instances.</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Scalar2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Scalar1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Scalar2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Scalar1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Scalar2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Scalar1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> 
                   <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> 
                   <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                   <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                   <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> 
                   <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> 
                  <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- k>auto</c->    <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                   <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
</pre>
   <p>The first six function templates,</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>Scalar2</c-> <c- n>s2</c-><c- p>)</c-></code>, and</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>Scalar1</c-> <c- n>s1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>)</c-></code></p>
   </ul>
   <p>perform pre- and post-multiplication of a <em>MathObj</em> instance by a scalar value.</p>
   <p>The next two function templates,</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>)</c-></code> and</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>)</c-></code></p>
   </ul>
   <p>perform the inner product and outer product, respectively.  Although hidden
by the <code class="highlight"><c- k>auto</c-></code> return type, per the multiplication traits described above, 
the inner product returns a promoted scalar and the outer product returns 
a <code class="highlight"><c- n>matrix</c-></code>, as expected.</p>
   <p>The last five function templates,</p>
   <ul>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>)</c-></code>,</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>rv1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>)</c-></code>, and</p>
    <li data-md>
     <p><code class="highlight"><c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>)</c-></code></p>
   </ul>
   <p>perform matrix multiplication of <em>MathObj</em>s.</p>
   <p>The question may arise as to why thirteen multiplication operators
are provided rather than the expected fifteen.  Strictly speaking, 
it is certainly possible to specify multiplication operators for <code class="highlight"><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>>*</c-><c- n>row_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- o>></c-></code> and <code class="highlight"><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- o>>*</c-><c- n>column_vector</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- o>></c-></code>, 
but these represent degenerate cases of vectors having one element, 
and so are not included in this revision.</p>
   <h3 class="heading settled" data-level="6.11" id="type-aliases"><span class="secno">6.11. </span><span class="content">Type Aliases</span><a class="self-link" href="#type-aliases"></a></h3>
   <p>Some type aliases provide useful shorthand symbols for the most common
compositions of types.</p>
<pre class="highlight"><c- c1>//- Convenience aliases for dynamically-resizable MathObjs</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>using</c-> <c- n>dyn_column_vector</c-> <c- o>=</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>using</c-> <c- n>dyn_col_vector</c-> <c- o>=</c-> <c- n>dyn_column_vector</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>using</c-> <c- n>dyn_row_vector</c-> <c- o>=</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- k>class</c-> <c- nc>A</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- n>T</c-><c- o>>></c->
<c- k>using</c-> <c- n>dyn_matrix</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>A</c-><c- o>>></c-><c- p>;</c->

<c- c1>//- Convenience aliases for fixed-size MathObjs</c->
<c- c1>//</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- o>></c->
<c- k>using</c-> <c- n>fs_column_vector</c-> <c- o>=</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- mi>1</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- o>></c->
<c- k>using</c-> <c- n>fs_col_vector</c-> <c- o>=</c-> <c- n>fs_column_vector</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Rows</c-><c- o>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- o>></c->
<c- k>using</c-> <c- n>fs_row_vector</c-> <c- o>=</c-> <c- n>row_vector</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- n>Cols</c-><c- o>>></c-><c- p>;</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- o>></c->
<c- k>using</c-> <c- n>fs_matrix</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>>></c-><c- p>;</c->
</pre>
   <h3 class="heading settled" data-level="6.12" id="expression-results"><span class="secno">6.12. </span><span class="content">Expression Results</span><a class="self-link" href="#expression-results"></a></h3>
   <p>The following are some expressions that demonstrate how element and
engine promotions are performed.</p>
<pre class="highlight"><c- k>using</c-> <c- n>cx_float</c->  <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c-><c- p>;</c->
<c- k>using</c-> <c- n>cx_double</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>complex</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c-><c- p>;</c->
<c- k>using</c-> <c- k>namespace</c-> <c- n>std</c-><c- o>::</c-><c- n>la</c-><c- p>;</c->

<c- b>void</c-> <c- nf>t1</c-><c- p>()</c->
<c- p>{</c->
    <c- b>float</c->       <c- n>f</c-> <c- o>=</c-> <c- mf>1.0f</c-><c- p>;</c->
    <c- b>double</c->      <c- n>d</c-> <c- o>=</c-> <c- mf>1.0</c-><c- p>;</c->
    <c- n>cx_double</c->   <c- n>Cols</c-> <c- o>=</c-> <c- p>{</c-><c- mf>1.0</c-><c- p>,</c-> <c- mf>0.0</c-><c- p>};</c->

    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->           <c- n>dmf</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->          <c- n>dmd</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- n>cx_double</c-><c- o>></c->       <c- n>dmc</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->

    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->      <c- n>fmf</c-><c- p>;</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->     <c- n>fmd</c-><c- p>;</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- n>cx_double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->  <c- n>fmc</c-><c- p>;</c->

    <c- k>auto</c->    <c- n>m01</c-> <c- o>=</c-> <c- n>dmf</c-><c- o>*</c-><c- n>fmf</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;float></c->
    <c- k>auto</c->    <c- n>m02</c-> <c- o>=</c-> <c- n>dmd</c-><c- o>*</c-><c- n>fmd</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;double></c->
    <c- k>auto</c->    <c- n>m03</c-> <c- o>=</c-> <c- n>dmc</c-><c- o>*</c-><c- n>fmc</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;complex&lt;double>></c->

    <c- k>auto</c->    <c- n>m04</c-> <c- o>=</c-> <c- n>fmf</c-><c- o>*</c-><c- n>dmf</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;float></c->
    <c- k>auto</c->    <c- n>m05</c-> <c- o>=</c-> <c- n>fmd</c-><c- o>*</c-><c- n>dmd</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;double></c->
    <c- k>auto</c->    <c- n>m06</c-> <c- o>=</c-> <c- n>fmc</c-><c- o>*</c-><c- n>dmc</c-><c- p>;</c->      <c- c1>//- dyn_matrix&lt;complex&lt;double>></c->

    <c- k>auto</c->    <c- n>m07</c-> <c- o>=</c-> <c- n>fmf</c-><c- o>*</c-><c- n>fmd</c-><c- p>;</c->      <c- c1>//- fs_matrix&lt;double, 3, 3></c->
    <c- k>auto</c->    <c- n>m08</c-> <c- o>=</c-> <c- n>fmd</c-><c- o>*</c-><c- n>fmc</c-><c- p>;</c->      <c- c1>//- fs_matrix&lt;complex&lt;double>, 3, 3></c->
<c- p>}</c->

<c- b>void</c-> <c- nf>t2</c-><c- p>()</c->
<c- p>{</c->
    <c- n>dyn_col_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->       <c- n>dcvf</c-><c- p>(</c-><c- mi>3</c-><c- p>);</c->
    <c- n>dyn_col_vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->      <c- n>dcvd</c-><c- p>(</c-><c- mi>3</c-><c- p>);</c->

    <c- n>fs_col_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->     <c- n>fcvf</c-><c- p>;</c->
    <c- n>fs_col_vector</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->    <c- n>fcvd</c-><c- p>;</c->

    <c- n>dyn_row_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->       <c- n>drvf</c-><c- p>(</c-><c- mi>3</c-><c- p>);</c->
    <c- n>dyn_row_vector</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->      <c- n>drvd</c-><c- p>(</c-><c- mi>3</c-><c- p>);</c->

    <c- n>fs_row_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->     <c- n>frvf</c-><c- p>;</c->
    <c- n>fs_row_vector</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->    <c- n>frvd</c-><c- p>;</c->

    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->          <c- n>dmd</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->           <c- n>dmf</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->           <c- n>dmf_cv</c-><c- p>(</c-><c- mi>3</c-><c- p>,</c-> <c- mi>1</c-><c- p>);</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->           <c- n>dmf_rv</c-><c- p>(</c-><c- mi>1</c-><c- p>,</c-> <c- mi>3</c-><c- p>);</c->

    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->     <c- n>fmd</c-><c- p>;</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->      <c- n>fmf</c-><c- p>;</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>1</c-><c- o>></c->      <c- n>fmf_cv</c-><c- p>;</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>1</c-><c- p>,</c-> <c- mi>3</c-><c- o>></c->      <c- n>fmf_rv</c-><c- p>;</c->

    <c- k>auto</c->    <c- n>r01</c-> <c- o>=</c-> <c- n>dmf</c-> <c- o>*</c-> <c- n>dcvf</c-><c- p>;</c->       <c- c1>//- dyn_col_vector&lt;float></c->
    <c- k>auto</c->    <c- n>r02</c-> <c- o>=</c-> <c- n>dmf_cv</c-> <c- o>*</c-> <c- n>drvf</c-><c- p>;</c->    <c- c1>//- dyn_matrix&lt;float></c->
    <c- k>auto</c->    <c- n>r03</c-> <c- o>=</c-> <c- n>drvf</c-> <c- o>*</c-> <c- n>dmf</c-><c- p>;</c->       <c- c1>//- dyn_row_vector&lt;float></c->
    <c- k>auto</c->    <c- n>r04</c-> <c- o>=</c-> <c- n>dcvf</c-> <c- o>*</c-> <c- n>fmf_rv</c-><c- p>;</c->    <c- c1>//- dyn_matrix&lt;float></c->

    <c- k>auto</c->    <c- n>r11</c-> <c- o>=</c-> <c- n>dmf</c-> <c- o>*</c-> <c- n>dcvd</c-><c- p>;</c->       <c- c1>//- dyn_col_vector&lt;double></c->
    <c- k>auto</c->    <c- n>r12</c-> <c- o>=</c-> <c- n>dmf_cv</c-> <c- o>*</c-> <c- n>drvd</c-><c- p>;</c->    <c- c1>//- dyn_matrix&lt;double></c->
    <c- k>auto</c->    <c- n>r13</c-> <c- o>=</c-> <c- n>drvf</c-> <c- o>*</c-> <c- n>dmd</c-><c- p>;</c->       <c- c1>//- dyn_row_vector&lt;double></c->
    <c- k>auto</c->    <c- n>r14</c-> <c- o>=</c-> <c- n>dcvd</c-> <c- o>*</c-> <c- n>dmf_rv</c-><c- p>;</c->    <c- c1>//- dyn_matrix&lt;double></c->

    <c- k>auto</c->    <c- n>r21</c-> <c- o>=</c-> <c- n>fmf</c-> <c- o>*</c-> <c- n>fcvf</c-><c- p>;</c->       <c- c1>//- fs_col_vector&lt;float, 3></c->
    <c- k>auto</c->    <c- n>r22</c-> <c- o>=</c-> <c- n>fmf_cv</c-> <c- o>*</c-> <c- n>frvf</c-><c- p>;</c->    <c- c1>//- fs_matrix&lt;float, 3, 3></c->
    <c- k>auto</c->    <c- n>r23</c-> <c- o>=</c-> <c- n>frvf</c-> <c- o>*</c-> <c- n>fmf</c-><c- p>;</c->       <c- c1>//- fs_row_vector&lt;float, 3></c->
    <c- k>auto</c->    <c- n>r24</c-> <c- o>=</c-> <c- n>fcvf</c-> <c- o>*</c-> <c- n>fmf_rv</c-><c- p>;</c->    <c- c1>//- fs_matrix&lt;float, 3, 3></c->

    <c- k>auto</c->    <c- n>r31</c-> <c- o>=</c-> <c- n>fmf</c-> <c- o>*</c-> <c- n>fcvd</c-><c- p>;</c->       <c- c1>//- fs_col_vector&lt;double, 3></c->
    <c- k>auto</c->    <c- n>r32</c-> <c- o>=</c-> <c- n>fmf_cv</c-> <c- o>*</c-> <c- n>frvd</c-><c- p>;</c->    <c- c1>//- fs_matrix&lt;double, 3, 3></c->
    <c- k>auto</c->    <c- n>r33</c-> <c- o>=</c-> <c- n>frvf</c-> <c- o>*</c-> <c- n>fmd</c-><c- p>;</c->       <c- c1>//- fs_row_vector&lt;3></c->
    <c- k>auto</c->    <c- n>r34</c-> <c- o>=</c-> <c- n>fcvd</c-> <c- o>*</c-> <c- n>fmf_rv</c-><c- p>;</c->    <c- c1>//- fs_matrix&lt;double, 3, 3></c->

    <c- k>auto</c->    <c- n>r41</c-> <c- o>=</c-> <c- n>drvf</c-> <c- o>*</c-> <c- n>dcvf</c-><c- p>;</c->      <c- c1>//- float</c->
    <c- k>auto</c->    <c- n>r42</c-> <c- o>=</c-> <c- n>frvf</c-> <c- o>*</c-> <c- n>dcvd</c-><c- p>;</c->      <c- c1>//- double</c->
    <c- k>auto</c->    <c- n>r43</c-> <c- o>=</c-> <c- n>frvd</c-> <c- o>*</c-> <c- n>fcvd</c-><c- p>;</c->      <c- c1>//- double</c->
<c- p>}</c->
</pre>
   <h2 class="heading settled" data-level="7" id="how-does-it-work"><span class="secno">7. </span><span class="content">How Does it Work?</span><a class="self-link" href="#how-does-it-work"></a></h2>
   <p>The preceding sections described the various components comprising the
interface, starting with the most basic, and proceeding in a bottom-up
fashion.  While this is useful for understanding the static structure of
the interface, it may help to look at how the interface works from a 
top-down perspective in order to understand how the pieces work together.</p>
   <p>Consider the following simple function:</p>
<pre class="highlight"><c- b>void</c-> <c- nf>f</c-><c- p>()</c->
<c- p>{</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c->     <c- n>fsmd</c-><c- p>;</c->         <c- c1>//- fixed-size matrix of double</c->
    <c- n>dyn_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->           <c- n>drmf</c-><c- p>(</c-><c- mi>4</c-><c- p>,</c-> <c- mi>5</c-><c- p>);</c->   <c- c1>//- dynamic matrix of float</c->

    <c- k>auto</c->    <c- n>m1</c-> <c- o>=</c-> <c- n>fsmd</c-> <c- o>*</c-> <c- n>drmf</c-><c- p>;</c->   <c- c1>//- dyn_matrix&lt;double> of size 3x5</c->
<c- p>}</c->
</pre>
   <p>One might reasonably ask: how does the library determine that <code class="highlight"><c- n>m1</c-></code> is a
dynamically-resizable matrix of double, and how does it know how to 
perform the requested multiplication?</p>
   <p>At a high level, the process for determining the return type of the binary
operators is as follows:</p>
   <ol>
    <li data-md>
     <p>An operator, say multiplication, is invoked.</p>
    <li data-md>
     <p>The operator examines the operator traits types of its two operands,
employing operator traits promotion to determine which of the two 
it will use to perform the multiplication; this operator traits 
type is also passed on as a template argument to the result type.</p>
    <li data-md>
     <p>The operator extracts the appropriate arithmetic traits type from the
operator traits.</p>
    <li data-md>
     <p>The arithmetic traits examines the engine types of the two operands,
employing engine promotion to determine the engine type of the result.</p>
    <li data-md>
     <p>The engine promotion traits examines the element types of the two
operands, employing element promotion to determine the element type of
the result.</p>
    <li data-md>
     <p>The element promotion traits determines a suitable element type that
can contain the result of the arithmetic operation with little or no 
loss of information.</p>
    <li data-md>
     <p>The engine promotion traits specifies the appropriate engine type
parametrized in terms of the resulting element type and other types
specific to that engine type.</p>
    <li data-md>
     <p>The arithmetic traits combines the engine type with the operator traits
type to specify the actual <em>MathObj</em> return type.</p>
    <li data-md>
     <p>The arithmetic traits provides a static member function that implements
the multiplication operation.</p>
    <li data-md>
     <p>The multiplication operator calls that function with the supplied operands
and returns the result.</p>
   </ol>
   <h3 class="heading settled" data-level="7.1" id="in-more-detail"><span class="secno">7.1. </span><span class="content">In More Detail</span><a class="self-link" href="#in-more-detail"></a></h3>
   <p>We describe the process in more detail in the following sections.  The reader
may find it helpful to follow along by looking at the strawman implementation
provided in the repo listed at the top of this document.</p>
   <h4 class="heading settled" data-level="7.1.1" id="calling-an-operator"><span class="secno">7.1.1. </span><span class="content">Calling an Operator</span><a class="self-link" href="#calling-an-operator"></a></h4>
   <p>Let’s begin by examining the the instantiation of matrix <code class="highlight"><c- n>m1</c-></code>, in which
the binary multiplication operator is invoked with operands <code class="highlight"><c- n>fsmd</c-></code> and <code class="highlight"><c- n>drmf</c-></code>.  The implementation of that operator might look like the following:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- o>></c->
<c- kr>inline</c-> <c- k>auto</c->
<c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>)</c->
<c- p>{</c->
    <c- k>using</c-> <c- n>op_traits</c->  <c- o>=</c-> <c- n>matrix_operator_traits_promotion_t</c-><c- o>&lt;</c-><c- n>OpTraits1</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op1_type</c->   <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op2_type</c->   <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>mul_traits</c-> <c- o>=</c-> 
        <c- k>typename</c-> <c- n>op_traits</c-><c- o>::</c-><c- k>template</c-> <c- n>multiplication_traits</c-><c- o>&lt;</c-><c- n>op1_type</c-><c- p>,</c-> <c- n>op2_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>return</c-> <c- n>mul_traits</c-><c- o>::</c-><c- n>multiply</c-><c- p>(</c-><c- n>m1</c-><c- p>,</c-> <c- n>m2</c-><c- p>);</c->
<c- p>}</c->
</pre>
   <p>The template parameters are deduced as:</p>
<pre class="highlight"><c- n>Eng1</c->  <c- o>-->></c->  <c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c->
<c- n>OpTraits1</c->  <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
<c- n>Eng2</c->  <c- o>-->></c->  <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c->
<c- n>OpTraits2</c->  <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
</pre>
   <h4 class="heading settled" data-level="7.1.2" id="selecting-the-operator-traits"><span class="secno">7.1.2. </span><span class="content">Selecting the Operator Traits</span><a class="self-link" href="#selecting-the-operator-traits"></a></h4>
   <p>The resulting operator traits type is then determined by instantiating the
alias template <code class="highlight"><c- n>matrix_operator_traits_promotion_t</c-></code> from Section 6.9 above:</p>
<pre class="highlight"><c- n>op_traits</c->  <c- o>-->></c->  <c- n>matrix_operator_traits_promotion_t</c-><c- o>&lt;</c-><c- n>default_matrix_operator_traits</c-><c- p>,</c->
                                                    <c- n>default_matrix_operator_traits</c-><c- o>></c->
           <c- o>-->></c->  <c- n>matrix_operator_traits_promotion</c-><c- o>&lt;</c-><c- n>default_matrix_operator_traits</c-><c- p>,</c->
                                                  <c- n>default_matrix_operator_traits</c-><c- o>>::</c-><c- n>alias_type</c->
           <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
</pre>
   <p>Now that the operator traits are known, we also know the four corresponding
arithmetic traits templates that will determine the resulting engine type 
and perform the actual computational work.</p>
   <p>The operand types are:</p>
<pre class="highlight"><c- n>op1_type</c->  <c- o>-->></c->  <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c-> 
                       <c- n>default_matrix_operator_traits</c-><c- o>></c->

<c- n>op2_type</c->  <c- o>-->></c->  <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c-><c- p>,</c-> 
                       <c- n>default_matrix_operator_traits</c-><c- o>></c->
</pre>
   <h4 class="heading settled" data-level="7.1.3" id="selecting-the-multiplication-traits"><span class="secno">7.1.3. </span><span class="content">Selecting the Multiplication Traits</span><a class="self-link" href="#selecting-the-multiplication-traits"></a></h4>
   <p>Given the operand types and operator traits types, the multiplication
traits type is then determined using them, per Section 6.8:</p>
<pre class="highlight"><c- n>mul_traits</c->  <c- o>-->></c-> 
    <c- n>default_matrix_operator_traits</c-><c- o>::</c->
        <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c->
            <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c-><c- p>,</c->
            <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c-><c- p>,</c-> 
            <c- n>default_matrix_operator_traits</c-><c- o>></c->
</pre>
   <p>From Section 6.7.4 above, we can see that the appropriate multiplication
traits partial specialization is:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>Eng1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Eng2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraits2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_multiplication_engine_t</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>Eng2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>multiply</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng1</c-><c- p>,</c-> <c- n>OpTraits1</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                                 <c- n>matrix</c-><c- o>&lt;</c-><c- n>Eng2</c-><c- p>,</c-> <c- n>OpTraits2</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <h4 class="heading settled" data-level="7.1.4" id="selecting-the-engine-type"><span class="secno">7.1.4. </span><span class="content">Selecting the Engine Type</span><a class="self-link" href="#selecting-the-engine-type"></a></h4>
   <p>Now that we know the operator traits to be passed on to the resulting matrix,
and which specialization will perform the multiplication, the next step in 
the process is to determine the engine type of the result.  We know that 
the template arguments to the multiplication traits are:</p>
<pre class="highlight"><c- n>Eng1</c->       <c- o>-->></c->  <c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c->
<c- n>OpTraits1</c->  <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
<c- n>Eng2</c->       <c- o>-->></c->  <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c->
<c- n>OpTraits2</c->  <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
<c- n>OpTraitsR</c->  <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
</pre>
   <p>We use these to select the resulting engine type.  The instantiation of the
alias template <code class="highlight"><c- n>matrix_multiplication_engine_t</c-></code> takes us to the  partial 
specialization of engine promotion traits relevant to multiplication:</p>
<pre class="highlight"><c- n>engine_type</c->  <c- o>-->></c->  <c- n>matrix_multiplication_engine_t</c-><c- o>&lt;</c->
                       <c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c->
                       <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>>></c->
             <c- o>-->></c->  <c- n>matrix_multiplication_engine_promotion</c-><c- o>&lt;</c->
                       <c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c->
                       <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>>>::</c-><c- n>engine_type</c->
</pre>
   <p>From the example in Section 6.5.4 above, this partial specialization looks
like the following:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>Alloc2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_multiplication_engine_promotion</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>,</c-> 
                                              <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Alloc2</c-><c- o>>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>alloc_type</c->   <c- o>=</c-> 
        <c- k>typename</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator_traits</c-><c- o>&lt;</c-><c- n>Alloc2</c-><c- o>>::</c-><c- k>template</c-> <c- n>rebind_alloc</c-><c- o>&lt;</c-><c- n>element_type</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c->  <c- o>=</c-> <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- n>element_type</c-><c- p>,</c-> <c- n>alloc_type</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>We can see from the above that this example engine promotion traits will
specify a dynamically resizable engine as the result type.  The template 
arguments are:</p>
<pre class="highlight"><c- n>T1</c->     <c- o>-->></c->  <c- b>double</c->
<c- n>Rows1</c->  <c- o>-->></c->  <c- mi>3</c->
<c- n>Cols1</c->  <c- o>-->></c->  <c- mi>4</c->
<c- n>T2</c->     <c- o>-->></c->  <c- b>float</c->
<c- n>Alloc2</c-> <c- o>-->></c->  <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>></c->
</pre>
   <p>From these, we can determine the promoted element type.  The instantiation
of template alias <code class="highlight"><c- n>matrix_element_promotion_t</c-></code> leads to:</p>
<pre class="highlight"><c- n>element_type</c->  <c- o>-->></c->  <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- b>float</c-><c- o>></c->
              <c- o>-->></c->  <c- n>matrix_element_promotion</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- b>float</c-><c- o>>::</c-><c- n>type</c->
              <c- o>-->></c->  <c- b>double</c->
</pre>
   <p>We next use the rebinder facility from <code class="highlight"><c- n>std</c-><c- o>::</c-><c- n>allocator_traits</c-></code> to select
the resulting allocator type:</p>
<pre class="highlight"><c- n>alloc_type</c->  <c- o>-->></c->  <c- n>std</c-><c- o>::</c-><c- n>allocator_traits</c-><c- o>&lt;</c-><c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>>::</c-><c- n>rebind_alloc</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->
            <c- o>-->></c->  <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>></c->
</pre>
   <p>These are then combined to yield the resulting engine type:</p>
<pre class="highlight"><c- n>engine_type</c->  <c- o>-->></c->  <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c->
</pre>
   <p>Now that we know the engine type, it is possible to determine the template
arguments of the resulting matrix type.  Popping the instantiation stack 
and returning to <code class="highlight"><c- n>matrix_multiplication_traits</c-></code>, we now know that:</p>
<pre class="highlight"><c- n>engine_type</c->  <c- o>-->></c->  <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c->
<c- n>op_traits</c->    <c- o>-->></c->  <c- n>default_matrix_operator_traits</c->
</pre>
   <p>These now form the template arguments of resulting matrix type:</p>
<pre class="highlight"><c- n>result_type</c->  <c- o>-->></c->  <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c-><c- p>,</c-> 
                          <c- n>default_matrix_operator_traits</c-><c- o>></c->
</pre>
   <h4 class="heading settled" data-level="7.1.5" id="the-fully-instantiated-multiplication-traits"><span class="secno">7.1.5. </span><span class="content">The Fully Instantiated Multiplication Traits</span><a class="self-link" href="#the-fully-instantiated-multiplication-traits"></a></h4>
   <p>So, after all of the preceding instantiations are done, the fully specialized
matrix multiplication traits looks like this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c->
            <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- mi>3</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c-><c- p>,</c->
            <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c-><c- p>,</c-> 
            <c- n>default_matrix_operator_traits</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>default_matrix_operator_traits</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c-><c- p>,</c-> 
                               <c- n>default_matrix_operator_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> 
    <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>double</c-><c- o>>></c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c->  
      <c- n>multiply</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- b>double</c-><c- p>,</c-><c- mi>3</c-><c- p>,</c-><c- mi>4</c-><c- o>></c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c->
               <c- n>matrix</c-><c- o>&lt;</c-><c- n>dr_matrix_engine</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- n>std</c-><c- o>::</c-><c- n>allocator</c-><c- o>&lt;</c-><c- b>float</c-><c- o>>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <p>(NB: this not a user-supplied specialization; rather, it is inteded to
represent what the compiler "sees" internally.)</p>
   <p>Finally, the binary multiplication operator wraps the call to <code class="highlight"><c- n>mulitply</c-><c- p>()</c-></code>,
returning the result as determined above.</p>
   <h2 class="heading settled" data-level="8" id="customization"><span class="secno">8. </span><span class="content">Customization</span><a class="self-link" href="#customization"></a></h2>
   <p>The library provides for three forms of customization: custom element types,
custom engines, and custom arithmetical operations.  The following sections
show examples of each.</p>
   <h3 class="heading settled" data-level="8.1" id="integrating-a-new-element-type"><span class="secno">8.1. </span><span class="content">Integrating a New Element Type</span><a class="self-link" href="#integrating-a-new-element-type"></a></h3>
   <p>Suppose that you have created a new type that models a real number in some
way and you wish for that type to be used as a matrix element:</p>
<pre class="highlight"><c- k>class</c-> <c- nc>NewNum</c-> 
<c- p>{</c->
  <c- k>public</c-><c- o>:</c->
    <c- n>NewNum</c-><c- p>();</c->
    <c- n>NewNum</c-><c- p>(</c-><c- n>NewNum</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>NewNum</c-><c- p>(</c-><c- n>NewNum</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- p>(</c-><c- n>U</c-> <c- n>other</c-><c- p>);</c->

    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>NewNum</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>NewNum</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>U</c-> <c- n>rhs</c-><c- p>);</c->

    <c- n>NewNum</c->     <c- k>operator</c-> <c- o>-</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->
    <c- n>NewNum</c->     <c- k>operator</c-> <c- o>+</c-><c- p>()</c-> <c- k>const</c-><c- p>;</c->

    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>+=</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>-=</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>*=</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
    <c- n>NewNum</c-><c- o>&amp;</c->     <c- k>operator</c-> <c- o>/=</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->

    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- o>+=</c-><c- p>(</c-><c- n>U</c-> <c- n>rhs</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- o>-=</c-><c- p>(</c-><c- n>U</c-> <c- n>rhs</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- o>*=</c-><c- p>(</c-><c- n>U</c-> <c- n>rhs</c-><c- p>);</c->
    <c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c->   <c- n>NewNum</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- o>/=</c-><c- p>(</c-><c- n>U</c-> <c- n>rhs</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- p>...</c->     <c- c1>//- implementation stuff</c->
<c- p>};</c->

<c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>==</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>==</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>U</c-> <c- n>rhs</c-><c- p>);</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>==</c-><c- p>(</c-><c- n>U</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
<c- p>...</c->
<c- c1>//- other comparison operators...</c->
<c- p>...</c->
<c- c1>//- other arithmetic operators...</c->
<c- p>...</c->
<c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>NewNum</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>U</c-> <c- n>rhs</c-><c- p>);</c->
<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>U</c-><c- o>></c-> <c- kr>inline</c-> <c- b>bool</c-> <c- k>operator</c-> <c- o>*</c-><c- p>(</c-><c- n>U</c-> <c- n>lhs</c-><c- p>,</c-> <c- n>NewNum</c-> <c- n>rhs</c-><c- p>);</c->
</pre>
   <p>Assuming that this type works as intended, and that all arithmetic
interactions with other types are handled the set of operator overloads 
that you provide, then all that is required for the library to accept <code class="highlight"><c- n>NewNum</c-></code> as an element type is this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <c- n>std</c-><c- o>::</c-><c- n>is_matrix_element</c-><c- o>&lt;</c-><c- n>NewNum</c-><c- o>></c-> <c- o>:</c-> <c- k>public</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c->
<c- p>{};</c->
</pre>
   <p>By stating that the type is a matrix element type, and by ensuring that its
arithmetic operators functions as promised, the library’s traits types will
allow compiliation to succeed.</p>
   <p>However, if the default arithmetic traits do not understand how to use your
new element type, then you will need to provide specializations of them as 
well.</p>
   <h3 class="heading settled" data-level="8.2" id="integrating-a-new-engine-type"><span class="secno">8.2. </span><span class="content">Integrating a New Engine Type</span><a class="self-link" href="#integrating-a-new-engine-type"></a></h3>
   <p>Suppose that you want to create a custom fixed-size matrix engine that is
somehow different from <code class="highlight"><c- n>fs_matrix_engine</c-></code>; perhaps it is instrumented in
some way for debugging, or uses fixed-size storage that is external to
the engine object.  It might look like this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- o>></c->
<c- k>class</c-> <c- nc>fs_matrix_engine_TST</c->
<c- p>{</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Rows</c-> <c- o>>=</c-> <c- mi>1</c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Cols</c-> <c- o>>=</c-> <c- mi>1</c-><c- p>);</c->

  <c- k>public</c-><c- o>:</c->
    <c- k>using</c-> <c- n>element_type</c->   <c- o>=</c-> <c- n>T</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_dense</c->       <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_rectangular</c-> <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_resizable</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>false_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>is_row_major</c->   <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>true_type</c-><c- p>;</c->
    <c- k>using</c-> <c- n>size_tuple</c->     <c- o>=</c-> <c- n>std</c-><c- o>::</c-><c- n>tuple</c-><c- o>&lt;</c-><c- b>size_t</c-><c- p>,</c-> <c- b>size_t</c-><c- o>></c-><c- p>;</c->

  <c- k>public</c-><c- o>:</c->
    <c- n>fs_matrix_engine_TST</c-><c- p>()</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine_TST</c-><c- p>(</c-><c- n>fs_matrix_engine_TST</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine_TST</c-><c- p>(</c-><c- n>fs_matrix_engine_TST</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->

    <c- n>fs_matrix_engine_TST</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>fs_matrix_engine_TST</c-><c- o>&amp;&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->
    <c- n>fs_matrix_engine_TST</c-><c- o>&amp;</c->   <c- k>operator</c-> <c- o>=</c-><c- p>(</c-><c- n>fs_matrix_engine_TST</c-> <c- k>const</c-><c- o>&amp;</c-><c- p>)</c-> <c- o>=</c-> <c- k>default</c-><c- p>;</c->

    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c->           <c- nf>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>)</c-> <c- k>const</c-><c- p>;</c->
    <c- n>T</c-> <c- k>const</c-><c- o>*</c->    <c- nf>data</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>columns</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>rows</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>size</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>size_t</c->      <c- nf>column_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- b>size_t</c->      <c- nf>row_capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->
    <c- n>size_tuple</c->  <c- nf>capacity</c-><c- p>()</c-> <c- k>const</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>);</c->
    <c- n>T</c-><c- o>&amp;</c->      <c- k>operator</c-> <c- p>()(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- n>T</c-><c- o>*</c->      <c- nf>data</c-><c- p>()</c-> <c- k>noexcept</c-><c- p>;</c->

    <c- b>void</c->    <c- nf>swap_columns</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->
    <c- b>void</c->    <c- nf>swap_rows</c-><c- p>(</c-><c- b>size_t</c-> <c- n>i</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>j</c-><c- p>);</c->

  <c- k>private</c-><c- o>:</c->
    <c- p>...</c->     <c- c1>//- implementation stuff</c->
<c- p>};</c->
</pre>
   <p>For each arithmetic operation in which you expect the new engine type to
be involved, you will need to provide a specialization (full or partial) 
of the engine promotion traits for that operation.  For example, let’s 
assume that you’re only interested in addition operations involving two 
operands having the new engine type, or where one operand has the standard 
fixed-size engine and the other has the new engine.  Then your engine 
promotion traits might look like this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_engine_promotion</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>,</c-> 
                                        <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows2</c-><c- p>,</c-> <c- n>Cols2</c-><c- o>>></c->
<c- p>{</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Rows1</c-> <c- o>==</c-> <c- n>Rows2</c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Cols1</c-> <c- o>==</c-> <c- n>Cols2</c-><c- p>);</c->
    <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c->  <c- o>=</c-> <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>element_type</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_engine_promotion</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>,</c-> 
                                        <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows2</c-><c- p>,</c-> <c- n>Cols2</c-><c- o>>></c->
<c- p>{</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Rows1</c-> <c- o>==</c-> <c- n>Rows2</c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Cols1</c-> <c- o>==</c-> <c- n>Cols2</c-><c- p>);</c->
    <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c->  <c- o>=</c-> <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>element_type</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols1</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows2</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols2</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_engine_promotion</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>,</c-> 
                                        <c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows2</c-><c- p>,</c-> <c- n>Cols2</c-><c- o>>></c->
<c- p>{</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Rows1</c-> <c- o>==</c-> <c- n>Rows2</c-><c- p>);</c->
    <c- k>static_assert</c-><c- p>(</c-><c- n>Cols1</c-> <c- o>==</c-> <c- n>Cols2</c-><c- p>);</c->
    <c- k>using</c-> <c- n>element_type</c-> <c- o>=</c-> <c- n>matrix_element_promotion_t</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>T2</c-><c- o>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>engine_type</c->  <c- o>=</c-> <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>element_type</c-><c- p>,</c-> <c- n>Rows1</c-><c- p>,</c-> <c- n>Cols1</c-><c- o>></c-><c- p>;</c->
<c- p>};</c->
</pre>
   <p>As we can see, these promotion traits dictate the result engine type to
be the new engine type. Another option is that the result engine type 
be <code class="highlight"><c- n>fs_matrix_engine</c-></code>; yet another option is that the return engine type
be some other type, like an expression engine.</p>
   <p>What about performing the computation?  If the default implementation of
the addition arithmetic traits understands how to perform the addition 
operation, then you are done.</p>
   <p>However, if the default addition traits don’t understand how to use the
new engine type, then you will also have to write specializations of the 
corresponding addition traits types.  That might look something like this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_addition_engine_t</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> 
                                                 <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>add</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                            <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_addition_engine_t</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> 
                                                 <c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>add</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                            <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->

<c- k>template</c-><c- o>&lt;</c-><c- k>class</c-> <c- nc>T1</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Rows</c-><c- p>,</c-> <c- b>size_t</c-> <c- n>Cols</c-><c- p>,</c-> <c- k>class</c-> <c- nc>T2</c-><c- p>,</c-> <c- k>class</c-> <c- nc>OpTraitsR</c-><c- o>></c->
<c- k>struct</c-> <c- n>matrix_addition_traits</c-><c- o>&lt;</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-><c- p>,</c-> 
                              <c- n>OpTraitsR</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_addition_engine_t</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> 
                                                 <c- n>fs_matrix_engine_</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>>></c-><c- p>;</c->
    <c- k>using</c-> <c- n>op_traits</c->   <c- o>=</c-> <c- n>OpTraitsR</c-><c- p>;</c->
    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>matrix</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>op_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>add</c-><c- p>(</c-><c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T1</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                            <c- n>matrix</c-><c- o>&lt;</c-><c- n>fs_matrix_engine_TST</c-><c- o>&lt;</c-><c- n>T2</c-><c- p>,</c-> <c- n>Rows</c-><c- p>,</c-> <c- n>Cols</c-><c- o>></c-><c- p>,</c-> <c- n>OpTraitsR</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m2</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <p>Note that namespace qualifiers which should actually appear in the above
code have been ommitted in the interest of brevity.</p>
   <h3 class="heading settled" data-level="8.3" id="customizing-an-arithmetic-operation"><span class="secno">8.3. </span><span class="content">Customizing an Arithmetic Operation</span><a class="self-link" href="#customizing-an-arithmetic-operation"></a></h3>
   <p>Suppose that you are working on a game engine, and you are interested in
experimenting with different algorithms for performing affine transforms
on spatial vectors.  To do this, you might be using fixed-size 4 x 4 matrices
and fixed size column vectors of size 4 x 1.  To test your new algorithm(s),
you could specialize the multiplication traits, which might look like this:</p>
<pre class="highlight"><c- k>template</c-><c- o>&lt;></c->
<c- k>struct</c-> <c- n>matrix_multiplication_traits</c-><c- o>&lt;</c-><c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>fs_column_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-><c- p>,</c-> 
                                    <c- n>default_matrix_operator_traits</c-><c- o>></c->
<c- p>{</c->
    <c- k>using</c-> <c- n>engine_type</c-> <c- o>=</c-> <c- n>matrix_multiplication_engine_t</c-><c- o>&lt;</c-><c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>4</c-><c- o>>::</c-><c- n>engine_type</c-><c- p>,</c-> 
                                                       <c- n>fs_column_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- o>>::</c-><c- n>engine_type</c-><c- o>></c-><c- p>;</c->

    <c- k>using</c-> <c- n>result_type</c-> <c- o>=</c-> <c- n>column_vector</c-><c- o>&lt;</c-><c- n>engine_type</c-><c- p>,</c-> <c- n>default_matrix_operator_traits</c-><c- o>></c-><c- p>;</c->

    <c- k>static</c-> <c- n>result_type</c->  <c- nf>multiply</c-><c- p>(</c-><c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>m1</c-><c- p>,</c-> 
                                 <c- n>fs_column_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c-> <c- k>const</c-><c- o>&amp;</c-> <c- n>cv2</c-><c- p>);</c->
<c- p>};</c->
</pre>
   <p>With this specialization visible, the following code would call the new,
specialized <code class="highlight"><c- n>multiply</c-><c- p>()</c-></code> member function, and thus employ your new algorithm:</p>
<pre class="highlight"><c- b>void</c-> <c- nf>f</c-><c- p>()</c->
<c- p>{</c->
    <c- n>fs_matrix</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c->      <c- n>m1</c-><c- p>;</c->
    <c- n>fs_column_vector</c-><c- o>&lt;</c-><c- b>float</c-><c- p>,</c-> <c- mi>4</c-><c- o>></c->  <c- n>cv1</c-><c- p>,</c-> <c- n>cvr</c-><c- p>;</c->

    <c- n>cvr</c-> <c- o>=</c-> <c- n>m1</c-> <c- o>*</c-> <c- n>cv1</c-><c- p>;</c->
<c- p>}</c->
</pre>
   <h2 class="heading settled" data-level="9" id="future-directions"><span class="secno">9. </span><span class="content">Future Directions</span><a class="self-link" href="#future-directions"></a></h2>
   <h3 class="heading settled" data-level="9.1" id="kona-feedback"><span class="secno">9.1. </span><span class="content">Kona Feedback</span><a class="self-link" href="#kona-feedback"></a></h3>
   <p>At the Kona 2019 meeting, draft version D1 of this paper was reviewed by
LEWG(I) and a joint session of SG14 and SG19.  Both reviews were generally 
positive, several good suggestions were made, and some polls regarding 
future directions were taken.</p>
   <h4 class="heading settled" data-level="9.1.1" id="lewg-i-polls-and-feedback-wednesday-2019-02-20"><span class="secno">9.1.1. </span><span class="content">LEWG(I) Polls and Feedback (Wednesday 2019-02-20)</span><a class="self-link" href="#lewg-i-polls-and-feedback-wednesday-2019-02-20"></a></h4>
   <p>There were a few polls taken in this session:</p>
   <ol>
    <li data-md>
     <p>We want 0-based indexing as opposed to 1-based indexing. <br> (unanimous: 20)</p>
    <li data-md>
     <p>We like having separate row_vector and column_vector types in addition to
   matrix. <br> SF F N A SA (21 present)<br> 3 0 5 4  4</p>
    <li data-md>
     <p>We want explicitly named operations (e.g., dot and outer) in addition to
   operators. <br> SF F N A SA (21 present) <br> 8 5 2 1  0</p>
    <li data-md>
     <p>Define engine/matrix classes in terms of mdspan + storage and mdspan concepts
   (e.g., extents), and expose an mdspan-esque interface.  This implies that 
   fs_ and dyn_ are combined into one template parametrized on extents (which 
   are either static or dynamic). <br> SF F N A SA (22 present) <br> 6 2 7 0  0</p>
   </ol>
   <p>There were some additional requests:</p>
   <ul>
    <li data-md>
     <p>Provide some implementation and usage experience.</p>
    <li data-md>
     <p>Provide a comparison with prior art.</p>
    <li data-md>
     <p>Explore the re-usability of <code class="highlight"><c- n>mdspan</c-></code> and <code class="highlight"><c- n>common_type</c-></code>.</p>
    <li data-md>
     <p>Be careful of allowing specializations of traits types that are part of
  namespace <code class="highlight"><c- n>std</c-></code>; be consistent with other traits.</p>
   </ul>
   <h4 class="heading settled" data-level="9.1.2" id="feedback-from-joint-sg14-sg19-session-friday-2019-02-22"><span class="secno">9.1.2. </span><span class="content">Feedback From Joint SG14/SG19 Session (Friday 2019-02-22)</span><a class="self-link" href="#feedback-from-joint-sg14-sg19-session-friday-2019-02-22"></a></h4>
   <ul>
    <li data-md>
     <p>Stick to 0-based indexing, for compatibility with current practice, and also
  for performance reasons.</p>
    <li data-md>
     <p>Provide a fixed-size engine whose memory is dynamically allocated.</p>
    <li data-md>
     <p>In this session, there was broad agreement that the one-vector approach
  advocated by LEWG(I) was the way to proceed.</p>
    <li data-md>
     <p>Outer product computation is rare in practice, therefore the vector-vector
  multiplication operator should return the inner product, and the outer
  product should be a named function.</p>
   </ul>
   <h4 class="heading settled" data-level="9.1.3" id="other-suggestions-gathered-received-at-kona"><span class="secno">9.1.3. </span><span class="content">Other Suggestions Gathered Received at Kona</span><a class="self-link" href="#other-suggestions-gathered-received-at-kona"></a></h4>
   <ul>
    <li data-md>
     <p>Figure out how to incorporate executors for concurrent operations.</p>
    <li data-md>
     <p>Per SG20’s recent guidance, include a "Gor table" (for example, see <a href="http://wg21.link/p1362r0">P1362R0</a>, Section 4.4) showing feature levels 
   and anticipated user sophistication for each.</p>
    <li data-md>
     <p>Include tutorial material on how the library can be used and extended, with
  several illustrative examples.</p>
   </ul>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>