<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1217: Quaternion support</title>
<meta property="og:title" content="Issue 1217: Quaternion support">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1217.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#NAD">NAD</a> status.</em></p>
<h3 id="1217"><a href="lwg-closed.html#1217">1217</a>. Quaternion support</h3>
<p><b>Section:</b> 29.4 <a href="https://wg21.link/complex.numbers">[complex.numbers]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Ted Shaneyfelt <b>Opened:</b> 2009-09-26 <b>Last modified:</b> 2019-02-26</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#complex.numbers">issues</a> in [complex.numbers].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Concerning mathematically proper operation of the type:
</p>

<blockquote><pre>
complex&lt;complex&lt;T&gt; &gt;
</pre></blockquote>

<p>
Generally accepted mathematical semantics of such a construct correspond
to quaternions through Cayly-Dickson construct
</p>

<blockquote><pre>
(w+xi) + (y+zi) j
</pre></blockquote>

<p>
The proper implementation seems straightforward by adding a few
declarations like those below. I have included operator definition for
combining real scalars and complex types, as well, which seems
appropriate, as algebra of complex numbers allows mixing complex and
real numbers with operators. It also allows for constructs such as
<code>complex&lt;double&gt; i=(0,1),  x = 12.34 + 5*i;</code>
</p>

<p>
Quaternions are often used in areas such as computer graphics, where,
for example, they avoid the problem of Gimbal lock when rotating objects
in 3D space, and can be more efficient than matrix multiplications,
although I am applying them to a different field.
</p>

<pre>
/////////////////////////ALLOW OPERATORS TO COMBINE REAL SCALARS AND COMPLEX VALUES /////////////////////////
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator+(const complex&lt;T&gt; x,const S a) {
    complex&lt;T&gt; result(x.real()+a, x.imag());
    return result;
}
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator+(const S a,const complex&lt;T&gt; x) {
    complex&lt;T&gt; result(a+x.real(), x.imag());
    return result;
}
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator-(const complex&lt;T&gt; x,const S a) {
    complex&lt;T&gt; result(x.real()-a, x.imag());
    return result;
}
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator-(const S a,const complex&lt;T&gt; x) {
    complex&lt;T&gt; result(a-x.real(), x.imag());
    return result;
}
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator*(const complex&lt;T&gt; x,const S a) {
    complex&lt;T&gt; result(x.real()*a, x.imag()*a);
    return result;
}
template&lt;typename T,typename S&gt; complex&lt;T&gt; operator*(const S a,const complex&lt;T&gt; x) {
    complex&lt;T&gt; result(a*x.real(), a*x.imag());
    return result;
}

/////////////////////////PROPERLY IMPLEMENT QUATERNION SEMANTICS/////////////////////////
template&lt;typename T&gt; double normSq(const complex&lt;complex&lt;T&gt; &gt;q) {
    return q.real().real()*q.real().real()
         + q.real().imag()*q.real().imag()
         + q.imag().real()*q.imag().real()
         + q.imag().imag()*q.imag().imag();
}
template&lt;typename T&gt; double norm(const complex&lt;complex&lt;T&gt; &gt;q) {
    return sqrt(normSq(q));
}
/////// Cayley-Dickson Construction
template&lt;typename T&gt; complex&lt;complex&lt;T&gt; &gt; conj(const complex&lt;complex&lt;T&gt; &gt; x) {
    complex&lt;complex&lt;T&gt; &gt; result(conj(x.real()),-x.imag());
    return result;
}
template&lt;typename T&gt; complex&lt;complex&lt;T&gt; &gt; operator*(const complex&lt;complex&lt;T&gt; &gt; ab,const complex&lt;complex&lt;T&gt; &gt; cd) {
    complex&lt;T&gt; re(ab.real()*cd.real()-conj(cd.imag())*ab.imag());
    complex&lt;T&gt; im(cd.imag()*ab.real()+ab.imag()*conj(cd.real()));
    complex&lt;complex&lt;double&gt; &gt; q(re,im);
    return q;
}
//// Quaternion division
template&lt;typename S,typename T&gt; complex&lt;complex&lt;T&gt; &gt; operator/(const complex&lt;complex&lt;T&gt; &gt; q,const S a) {
    return q * (1/a);
}
template&lt;typename S,typename T&gt; complex&lt;complex&lt;T&gt; &gt; operator/(const S a,const complex&lt;complex&lt;T&gt; &gt; q) {
    return a*conj(q)/normSq(q);
}
template&lt;typename T&gt; complex&lt;complex&lt;T&gt; &gt; operator/(const complex&lt;complex&lt;T&gt; &gt; n, const complex&lt;complex&lt;T&gt; &gt; d) {
    return n * (conj(d)/normSq(d));
}
</pre>

<p><i>[
2009-10 Santa Cruz:
]</i></p>


<blockquote><p>
NAD Future. There is no consensus or time to move this into C++0X.
</p></blockquote>

<p><i>[LEWG Kona 2017]</i></p>

<p>Recommend SG6 - We note that <code>complex&lt;complex&gt;</code> is the wrong way to spell this</p>

<p><i>[2017-03-03, Kona]</i></p>

<p>
SG6 suggests this issue is a new feature, not a problem with the existing
standard, and should therefore be closed NAD. However, SG6 invites papers that bring
the proposal up to date with the current standard.
</p>


<p id="res-1217"><b>Proposed resolution:</b></p>





</body>
</html>
