<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">


<title>N3131: Compile-time rational arithmetic and overflow</title>
<style type="text/css">
p {text-align:justify}
li {text-align:justify}
blockquote.note
{
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
}
ins, .inserted
{
    color: black;
    background: #a0ffa0;
    text-decoration: underline;
}
del
{
    color: black;
    background: #ffa0a0;
    text-decoration: line-through;
}
</style>
</head><body>
<table>
<tr><td>Document Number:</td><td>N3131=10-0121</td></tr>
<tr><td>Date:</td><td>2010-08-20</td></tr>
<tr><td>Author:</td><td><a href="mailto:anthony@justsoftwaresolutions.co.uk">Anthony
      Williams</a><br>Just Software Solutions Ltd</td></tr>
</table>
    <h1>N3131: Compile-time rational arithmetic and overflow</h1>

<p>Comment GB 89 on the FCD (see N3102) raised the issue of how
compile-time rational arithmetic should be done when the result is
representable, but a simple application of arithmetic rules would
  result in overflow.</p>

<p>e.g. <code>ratio_multiply&lt;ratio&lt;INTMAX_MAX,2&gt;,ratio&lt;2,INTMAX_MAX&gt;&gt;</code> can be
  reduced to <code>ratio&lt;1,1&gt;</code>, but the direct result
  of <code>ratio&lt;INTMAX_MAX*2,INTMAX_MAX*2&gt;</code> would result
  in overflow.</p>

<p>The consensus in Rapperswil was to allow but not require the
  implementation to handle such overflow if the final result was
  representable.</p>

<h2>Proposed Wording</h2>

<p>Change the wording in 20.6.2 [ratio.arithmetic] as follows:</p>

<blockquote>
  <p>Implementations may use other algorithms to compute these
    values. If overﬂow occurs <ins>in the calculation of the
    result</ins>, the program is ill-formed. <ins>[Note:
    Implementations are encouraged to use alternative algorithms that
    avoid overflow in the calculation if the final result is
    representable. Such provision is conditionally supported. -- End
    Note]</ins></p>


  <pre>template &lt;class R1, class R2&gt; using ratio_add = <em>see below</em>;</pre>

<p>The type <code>ratio_add&lt;R1, R2&gt;</code> shall be a synonym for
<del><code>ratio&lt;T1,T2&gt;</code></del> <ins><code>ratio&lt;U,
V&gt;</code> such that <code>ratio&lt;U,V&gt;::num</code> and
<code>ratio&lt;U,V&gt;::den</code> are the same as the corresponding
members of
<code>ratio&lt;T1,T2&gt;</code> would be in the absence of arithmetic
overflow</ins> where <code>T1</code> has the value <code>R1::num *
R2::den + R2::num * R1::den</code> and <code>T2</code> has the
value <code>R1::den * R2::den</code>. <ins>If the required values of
<code>ratio&lt;U,V&gt;::num</code>
  and <code>ratio&lt;U,V&gt;::den</code> cannot be represented
  in <code>intmax_t</code> then the program is illformed. Correct
  calculation of the result if either of <code>T1</code>
  or <code>T2</code> cannot be represented in <code>intmax_t</code>
  is conditionally supported ([defns.cond.supp])</ins></p>

<pre>
template &lt;class R1, class R2&gt; using ratio_subtract = <em>see below</em>;
</pre>

<p>
The type <code>ratio_subtract&lt;R1, R2&gt;</code> shall be a synonym for
<del><code>ratio&lt;T1,T2&gt;</code></del> <ins><code>ratio&lt;U,
V&gt;</code> such that <code>ratio&lt;U,V&gt;::num</code> and
<code>ratio&lt;U,V&gt;::den</code> are the same as the corresponding
members of
<code>ratio&lt;T1,T2&gt;</code> would be in the absence of arithmetic
overflow</ins> where <code>T1</code> has the value <code>R1::num *
R2::den - R2::num * R1::den</code> and <code>T2</code> has the
value <code>R1::den * R2::den</code>. <ins>If the required values of
<code>ratio&lt;U,V&gt;::num</code>
  and <code>ratio&lt;U,V&gt;::den</code> cannot be represented
  in <code>intmax_t</code> then the program is illformed. Correct
  calculation of the result if either of <code>T1</code>
  or <code>T2</code> cannot be represented in <code>intmax_t</code> is
  conditionally supported ([defns.cond.supp])</ins></p>

<pre>
template &lt;class R1, class R2&gt; using ratio_multiply = <em>see below</em>;
</pre>

<p>
The type <code>ratio_multiply&lt;R1, R2&gt;</code> shall be a synonym
for
<del><code>ratio&lt;T1,T2&gt;</code></del> <ins><code>ratio&lt;U,
V&gt;</code> such that <code>ratio&lt;U,V&gt;::num</code> and
<code>ratio&lt;U,V&gt;::den</code> are the same as the corresponding
members of
<code>ratio&lt;T1,T2&gt;</code> would be in the absence of arithmetic
overflow</ins> where <code>T1</code> has the value <code>R1::num *
R2::num</code> and <code>T2</code> has the value <code>R1::den *
R2::den</code>. <ins>If the required values of <code>ratio&lt;U,V&gt;::num</code>
and <code>ratio&lt;U,V&gt;::den</code> cannot be represented in <code>intmax_t</code> then the
program is illformed. Correct calculation of the result if either
of <code>T1</code> or <code>T2</code> cannot be represented
in <code>intmax_t</code> is conditionally supported
([defns.cond.supp])</ins></p>

<pre>template &lt;class R1, class R2&gt; using ratio_divide = <em>see below</em>;
</pre>

<p>The type <code>ratio_divide&lt;R1, R2&gt;</code> shall be a synonym for
<del><code>ratio&lt;T1,T2&gt;</code></del> <ins><code>ratio&lt;U,
V&gt;</code> such that <code>ratio&lt;U,V&gt;::num</code> and
<code>ratio&lt;U,V&gt;::den</code> are the same as the corresponding
members of
<code>ratio&lt;T1,T2&gt;</code> would be in the absence of arithmetic
overflow</ins> where <code>T1</code> has the value <code>R1::num *
R2::den</code> and <code>T2</code> has the value <code>R1::den *
R2::num</code>. <ins>If the required values
of <code>ratio&lt;U,V&gt;::num</code> and
<code>ratio&lt;U,V&gt;::den</code> cannot be represented in <code>intmax_t</code> then the program is
illformed. Correct
  calculation of the result if either of <code>T1</code>
  or <code>T2</code> cannot be represented in <code>intmax_t</code>
  is conditionally supported ([defns.cond.supp])</ins>
</p>

<p><ins>[Example --<br>

<pre>
static_assert(ratio_add&lt;ratio&lt;1,3&gt;,ratio&lt;1,6&gt;&gt;::num==1,"1/3+1/6==1/2");
static_assert(ratio_add&lt;ratio&lt;1,3&gt;,ratio&lt;1,6&gt;&gt;::den==2,"1/3+1/6==1/2");
static_assert(ratio_add&lt;ratio&lt;1,INTMAX_MAX&gt;,ratio&lt;1,INTMAX_MAX&gt;&gt;::num==2,"1/MAX+1/MAX==2/MAX");  // conditionally supported
static_assert(ratio_add&lt;ratio&lt;1,INTMAX_MAX&gt;,ratio&lt;1,INTMAX_MAX&gt;&gt;::den==INTMAX_MAX,"1/MAX+1/MAX==2/MAX");  // conditionally supported

static_assert(ratio_multiply&lt;ratio&lt;1,3&gt;,ratio&lt;3,2&gt;&gt;::num==1,"1/3*3/2==1/2");
static_assert(ratio_multiply&lt;ratio&lt;1,3&gt;,ratio&lt;3,2&gt;&gt;::den==2,"1/3*3/2==1/2");

static_assert(ratio_multiply&lt;ratio&lt;1,INTMAX_MAX&gt;,ratio&lt;INTMAX_MAX,2&gt;&gt;::num==1,"1/MAX * MAX/2==1/2");  // conditionally supported
static_assert(ratio_multiply&lt;ratio&lt;1,INTMAX_MAX&gt;,ratio&lt;INTMAX_MAX,2&gt;&gt;::den==2,"1/MAX * MAX/2==1/2");  // conditionally supported
</pre>

--End Example]</ins></p>

</blockquote>


</body></html>
