<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2592: Require that chrono::duration_casts from smaller durations to larger durations do not overflow</title>
<meta property="og:title" content="Issue 2592: Require that chrono::duration_casts from smaller durations to larger durations do not overflow">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2592.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#New">New</a> status.</em></p>
<h3 id="2592"><a href="lwg-active.html#2592">2592</a>. Require that <code>chrono::duration_cast</code>s from smaller durations to larger durations do not overflow</h3>
<p><b>Section:</b> 30.2 <a href="https://wg21.link/time.syn">[time.syn]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Andy Giese <b>Opened:</b> 2016-02-05 <b>Last modified:</b> 2016-05-08</p>
<p><b>Priority: </b>4
</p>
<p><b>View all other</b> <a href="lwg-index.html#time.syn">issues</a> in [time.syn].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Currently 30.2 <a href="https://wg21.link/time.syn">[time.syn]</a> states
</p>
<blockquote><pre>
<i>// convenience typedefs</i>
typedef duration&lt;<i>signed integer type of at least 64 bits</i>,        nano&gt; nanoseconds;
typedef duration&lt;<i>signed integer type of at least 55 bits</i>,       micro&gt; microseconds;
typedef duration&lt;<i>signed integer type of at least 45 bits</i>,       milli&gt; milliseconds;
typedef duration&lt;<i>signed integer type of at least 35 bits</i>             &gt; seconds;
typedef duration&lt;<i>signed integer type of at least 29 bits</i>, ratio&lt;  60&gt;&gt; minutes;
typedef duration&lt;<i>signed integer type of at least 23 bits</i>, ratio&lt;3600&gt;&gt; hours;
</pre></blockquote>
<p>
However, a <code>duration_cast&lt;minutes&gt;(seconds::max())</code> would cause overflow if the underlying signed integers 
only met the minimums specified.
<p/>
The standard should specify that implementations guarantee that a <code>duration_cast</code> from any smaller duration in 
these "convenience typedefs" will not overflow any larger duration. That is, <code>hours</code> should be able to hold 
the maximum of <code>minutes</code>, which should be able to hold the maximum of <code>seconds</code> and so on.
<p/>
More formally, if the ratio <code>typedef A</code> and <code>typedef B</code> is <code>1:Y</code> where <code>Y &gt; 1</code> (e.g., 
1 : 60 in case of <code>minutes</code> : <code>seconds</code>), then <code>#bits<sub>A</sub>-1</code> must be at least 
<code>ceil(log<sub>2</sub>(2<sup>#bits<sub>B</sub>-1)/Y)</sup>)</code>.
<p/>
In the case of <code>minutes</code> : <code>seconds</code>, <code>X = 1</code>, <code>Y = 60</code>. Let 
<code>#bits<sub>seconds</sub> = 32</code>. Therefore:
</p>
<ul>
<li><p><code>2<sup>(#bits<sub>seconds</sub> - 1)</sup> = 2<sup>31</sup> = 2147483648</code></p></li>
<li><p><code>ceil(log<sub>2</sub>(2<sup>31</sup> / 60) = 26</code></p></li>
<li><p><code>#bits<sub>minutes</sub> - 1 = 26</code></p></li>
<li><p><code>#bits<sub>minutes</sub> = 27</code></p></li>
</ul>
<p>
Therefore, a minimum of 27 bits would be needed to store <code>minutes</code> if 32 were used to store <code>seconds</code>.
<p/>
I propose to change the definitions of the convenience typedefs as follows:
</p>
<blockquote><pre>
<i>// convenience typedefs</i>
typedef duration&lt;<i>signed integer type of at least 64 bits</i>,        nano&gt; nanoseconds;
typedef duration&lt;<i>signed integer type of at least 55 bits</i>,       micro&gt; microseconds;
typedef duration&lt;<i>signed integer type of at least 46 bits</i>,       milli&gt; milliseconds;
typedef duration&lt;<i>signed integer type of at least 37 bits</i>             &gt; seconds;
typedef duration&lt;<i>signed integer type of at least 32 bits</i>, ratio&lt;  60&gt;&gt; minutes;
typedef duration&lt;<i>signed integer type of at least 27 bits</i>, ratio&lt;3600&gt;&gt; hours;
</pre></blockquote>
<p>
These bits were chosen to satisfy the above formula. Note that
minimums only increased, so larger ranges could be held. A nice
outcome of this choice is that <code>minutes</code> does not go above 32 bits.
</p>

<p><i>[2016-04-23, Tim Song comments]</i></p>

<p>
The P/R of LWG 2592 doesn't fix the issue it wants to solve, because the actual underlying type will likely 
have more bits than the specified minimum.
<p/>
Consider <code>seconds</code>, which the P/R requires to have at least 37 bits. On a typical system this implies 
using a 64-bit integer. To ensure that casting from <code>seconds::max()</code> to <code>minutes</code> doesn't overflow 
in such a system, it is necessary for the latter to have at least 59 bits (which means, in practice, 64 bits too), 
not just 32 bits. Thus, just changing the minimum number of bits will not be able to provide the desired guarantee 
that casting from a smaller unit to a larger one never overflow.
<p/>
If such a guarantee is to be provided, it needs to be spelled out directly. Note that the difference here is 9 bits 
(for the 1000-fold case) and 5 bits (for the 60-fold case), which is less than the size difference between integer 
types on common systems, so such a requirement would effectively require those convenience typedefs to use the 
same underlying integer type.
</p>


<p id="res-2592"><b>Proposed resolution:</b></p>
<p>This wording is relative to N4567.</p>

<ol>
<li><p>Change 30.2 <a href="https://wg21.link/time.syn">[time.syn]</a>, header <code>&lt;chrono&gt;</code> synopsis, as indicated</p>

<blockquote><pre>
[&hellip;]

<i>// convenience typedefs</i>
typedef duration&lt;<i>signed integer type of at least 64 bits</i>,        nano&gt; nanoseconds;
typedef duration&lt;<i>signed integer type of at least 55 bits</i>,       micro&gt; microseconds;
typedef duration&lt;<i>signed integer type of at least <ins>46</ins><del>45</del> bits</i>,       milli&gt; milliseconds;
typedef duration&lt;<i>signed integer type of at least <ins>37</ins><del>35</del> bits</i>             &gt; seconds;
typedef duration&lt;<i>signed integer type of at least <ins>32</ins><del>29</del> bits</i>, ratio&lt;  60&gt;&gt; minutes;
typedef duration&lt;<i>signed integer type of at least <ins>27</ins><del>23</del> bits</i>, ratio&lt;3600&gt;&gt; hours;

[&hellip;]
</pre></blockquote>

</li>
</ol>





</body>
</html>
