<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>Polishing chrono</title>

	<style>
	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 {color:#00A000}
	del {color:#A00000}
	code {white-space:pre;}
	</style>
</head>
<body>

<address align=right>
Document number: P0092R1<br>
<br/>
<br/>
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br/>
2015-10-20<br/>
</address>
<hr/>
<h1 align=center>Polishing <code>&lt;chrono&gt;</code></h1>

<h2>Difference from previous revision</h2>

<p>
Previous revision: <a href="p0092r0.html">P0092R0</a>
</p>

<ul>
<li>
Per request of the LEWG, removed the increment/decrement operator for
<code>time_point</code>.
</li>
<li>
Replaced "largest" with "greatest" in <code>floor</code> <i>Returns:</i>.
</li>
<li>
Replaced "smallest" with "least" in <code>ceil</code> <i>Returns:</i>.
</li>
<li>
Use "equidistant" in <code>round</code> <i>Returns:</i>.
</li>
<li>
Use "%2 == 0" for "even" in <code>round</code> <i>Returns:</i>.
</li>
<li>
Use numeric_limits&lt;duration&gt;::is_signed in <code>abs</code> <i>Remarks:</i>.
</li>
<li>
Replace "instantiation" with "specialization" in all <i>Remarks:</i>.
</li>
</ul>

<h2>Contents</h2>

<ul>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#Implementation">Implementation</a></li>
<li><a href="#Wording">Wording</a></li>
</ul>

<a name="Introduction"></a><h2>Introduction</h2>

<p>
This paper proposes a few minor additions to the chrono library to make it easier to
use and more uniform:
</p>

<ul>
<li><p>
Alternative rounding modes for durations and time_points:
</p>
<ul>
<li><code>floor</code>: round towards negative infinity.</li>
<li><code>ceil</code>: round towards positive infinity.</li>
<li><code>round</code>: : round towards nearest, to even on tie.</li>
</ul>
</li>
<li><p>
<code>abs</code> <i>only</i> for signed <code>duration</code> types.
</p></li>
</ul>

<p>
These are <i>minor</i> additions that make chrono easier to use.  They have been
implemented <b>and</b> used for years.  They should have been part of the original
chrono proposal for C++11, but simply slipped through the cracks by no one's fault
but my own.
</p>

<p>
The rounding modes differ from <code>duration_cast</code> and <code>time_point_cast</code>
in that these existing rounding functions truncate towards zero:  downwards for postive
values and upwards for negative values.
</p>

<a name="Implementation"></a><h2>Implementation</h2>

<p>
The implementation is shown below for the utility functions.  This presentation
is meant to:
</p>

<ul>
<li><p>
Fully inform the intent of this proposal.
</p></li>
<li><p>
Immediately convey the scope and the small-ness of this proposal.
</p></li>
<li><p>
Show the ease of implementation of this proposal.
</p></li>
</ul>

<p>
This implementation is consistent with that which has been up on
<a href="http://howardhinnant.github.io/duration_io/chrono_util.html">my personal website</a>
for years.
</p>

<blockquote><pre>
namespace std { namespace chrono {

namespace detail
{

template &lt;class T&gt;
struct is_duration
    : public false_type
    {};

template &lt;class Rep, class Period&gt;
struct is_duration&lt;duration&lt;Rep, Period&gt;&gt;
    : public true_type
    {};

}  // namespace detail

template &lt;class To, class Rep, class Period,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}&gt;&gt;
constexpr
To
floor(const duration&lt;Rep, Period&gt;&amp; d)
{
    To t = duration_cast&lt;To&gt;(d);
    if (t &gt; d)
        --t;
    return t;
}

template &lt;class To, class Rep, class Period,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}&gt;&gt;
constexpr
To
ceil(const duration&lt;Rep, Period&gt;&amp; d)
{
    To t = duration_cast&lt;To&gt;(d);
    if (t &lt; d)
        ++t;
    return t;
}

template &lt;class To, class Rep, class Period,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}
             &amp;&amp; !treat_as_floating_point&lt;typename To::rep&gt;{}&gt;&gt;
constexpr
To
round(const duration&lt;Rep, Period&gt;&amp; d)
{
    To t0 = floor&lt;To&gt;(d);
    To t1 = t0 + To{1};
    auto diff0 = d - t0;
    auto diff1 = t1 - d;
    if (diff0 == diff1)
    {
        if (t0.count() &amp; 1)
            return t1;
        return t0;
    }
    else if (diff0 &lt; diff1)
        return t0;
    return t1;
}

template &lt;class To, class Clock, class FromDuration,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}&gt;&gt;
constexpr
time_point&lt;Clock, To&gt;
floor(const time_point&lt;Clock, FromDuration&gt;&amp; tp)
{
    return time_point&lt;Clock, To&gt;{floor&lt;To&gt;(tp.time_since_epoch())};
}

template &lt;class To, class Clock, class FromDuration,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}&gt;&gt;
constexpr
time_point&lt;Clock, To&gt;
ceil(const time_point&lt;Clock, FromDuration&gt;&amp; tp)
{
    return time_point&lt;Clock, To&gt;{ceil&lt;To&gt;(tp.time_since_epoch())};
}

template &lt;class To, class Clock, class FromDuration,
          class = enable_if_t&lt;detail::is_duration&lt;To&gt;{}
             &amp;&amp; !treat_as_floating_point&lt;typename To::rep&gt;{}&gt;&gt;
constexpr
time_point&lt;Clock, To&gt;
round(const time_point&lt;Clock, FromDuration&gt;&amp; tp)
{
    return time_point&lt;Clock, To&gt;{round&lt;To&gt;(tp.time_since_epoch())};
}

template &lt;class Rep, class Period,
          class = enable_if_t
          &lt;
              duration&lt;Rep, Period&gt;::min() &lt; duration&lt;Rep, Period&gt;::zero()
          &gt; &gt;
constexpr
duration&lt;Rep, Period&gt;
abs(duration&lt;Rep, Period&gt; d)
{
    return d &gt;= d.zero() ? d : -d;
}

} }  // namespace std::chrono
</pre></blockquote>

<a name="Wording"></a><h2>Wording</h2>

<ul>

<li>
<p>
Add to 20.12.2 Header <code>&lt;chrono&gt;</code> synopsis [time.syn], under
<code>duration_cast</code>:
</p>
<blockquote><pre>
template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration floor(const duration&lt;Rep, Period&gt;&amp; d);

template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration ceil(const duration&lt;Rep, Period&gt;&amp; d);

template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration round(const duration&lt;Rep, Period&gt;&amp; d);
</pre></blockquote>
</li>

<li>
<p>
Add to 20.12.2 Header <code>&lt;chrono&gt;</code> synopsis [time.syn], under
<code>time_point_cast</code>:
</p>
<blockquote><pre>
template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    floor(const time_point&lt;Clock, Duration&gt;&amp; tp);

template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    ceil(const time_point&lt;Clock, Duration&gt;&amp; tp);

template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    round(const time_point&lt;Clock, Duration&gt;&amp; tp);
</pre></blockquote>
</li>

<li>
<p>
Add a new section to 20.12.2 Header <code>&lt;chrono&gt;</code> synopsis [time.syn]
(<i>specialized algorithms:</i> &mdash; within namespace <code>std::chrono</code>):
</p>
<blockquote><pre>
template &lt;class Rep, class Period&gt;
    constexpr duration&lt;Rep, Period&gt; abs(duration&lt;Rep, Period&gt; d)
</pre></blockquote>
</li>

<li>
<p>
Add to 20.12.5.7 <code>&lt;duration_cast&gt;</code> [time.duration.cast]:
</p>
<blockquote>
<pre>
template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration floor(const duration&lt;Rep, Period&gt;&amp; d);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>.
</p>
<p>
<i>Returns:</i> The greatest result <code>t</code> representable in <code>ToDuration</code>
for which <code>t &lt;= d</code>.
</p>
</blockquote>

<pre>
template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration ceil(const duration&lt;Rep, Period&gt;&amp; d);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>.
</p>
<p>
<i>Returns:</i> The least result <code>t</code> representable in <code>ToDuration</code>
for which <code>t &gt;= d</code>.
</p>
</blockquote>

<pre>
template &lt;class ToDuration, class Rep, class Period&gt;
    constexpr ToDuration round(const duration&lt;Rep, Period&gt;&amp; d);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>, and
<code>treat_as_floating_point&lt;typename ToDuration::rep&gt;::value</code> is
<code>false</code>.
</p>
<p>
<i>Returns:</i> The value of <code>ToDuration</code> that is closest to
<code>d</code>. If there are two closest values, then return the value
<code>t</code> for which <code>t % 2 == 0</code>.
</p>
</blockquote>

</blockquote>
</li>

<li>
<p>
Add a new section to 20.12.5 [time.duration]:  duration algorithms [time.duration.alg].
</p>
<blockquote>
<pre>
template &lt;class Rep, class Period&gt;
    constexpr duration&lt;Rep, Period&gt; abs(duration&lt;Rep, Period&gt; d)
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>numeric_limits&lt;Rep&gt;::is_signed</code> is <code>true</code>.
</p>
<p>
<i>Returns:</i> If <code>d &gt;= d.zero()</code>, return <code>d</code>, otherwise
return <code>-d</code>.
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Add to 20.12.6.7 <code>time_point_cast</code> [time.point.cast]:
</p>
<blockquote>

<pre>
template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    floor(const time_point&lt;Clock, Duration&gt;&amp; tp);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>.
</p>
<p>
<i>Returns:</i> <code>time_point&lt;Clock, ToDuration&gt;{floor&lt;ToDuration&gt;(tp.time_since_epoch())}</code>.
</p>
</blockquote>

<pre>
template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    ceil(const time_point&lt;Clock, Duration&gt;&amp; tp);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>.
</p>
<p>
<i>Returns:</i> <code>time_point&lt;Clock, ToDuration&gt;{ceil&lt;ToDuration&gt;(tp.time_since_epoch())}</code>.
</p>
</blockquote>

<pre>
template &lt;class ToDuration, class Clock, class Duration&gt;
    constexpr time_point&lt;Clock, ToDuration&gt;
    round(const time_point&lt;Clock, Duration&gt;&amp; tp);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This function shall not participate in overload resolution unless
<code>ToDuration</code> is a specialization of <code>duration</code>, and
<code>treat_as_floating_point&lt;typename ToDuration::rep&gt;::value</code> is
<code>false</code>.
</p>
<p>
<i>Returns:</i> <code>time_point&lt;Clock, ToDuration&gt;{round&lt;ToDuration&gt;(tp.time_since_epoch())}</code>.
</p>
</blockquote>

</blockquote>
</li>

<li>
<p>
Modify 20.12.5.5 <code>duration</code> non-member arithmetic [time.duration.nonmember]:
</p>

<blockquote>
<pre>
template &lt;class Rep1, class Period, class Rep2&gt;
  constexpr duration&lt;common_type_t&lt;Rep1, Rep2&gt;, Period&gt;
  operator/(const duration&lt;Rep1, Period&gt;&amp; d, const Rep2&amp; s);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This operator shall not participate in overload resolution
unless <code>Rep2</code> is implicitly convertible to
<code>CR(Rep1, Rep2)</code> and <code>Rep2</code> is not <del>an instantiation</del>
<ins>a specialization</ins> of <code>duration</code>.
</p>
</blockquote>

<p>...</p>

<pre>
template &lt;class Rep1, class Period, class Rep2&gt;
  constexpr duration&lt;common_type_t&lt;Rep1, Rep2&gt;, Period&gt;
  operator%(const duration&lt;Rep1, Period&gt;&amp; d, const Rep2&amp; s);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This operator shall not participate in overload resolution
unless <code>Rep2</code> is implicitly convertible to
<code>CR(Rep1, Rep2)</code> and <code>Rep2</code> is not <del>an instantiation</del>
<ins>a specialization</ins> of <code>duration</code>.
</p>
</blockquote>

</blockquote>
</blockquote>
</li>

<li>
<p>
Modify 20.12.5.7 <code>duration_cast</code> [time.duration.cast]:
</p>

<blockquote>
<pre>
template &lt;class ToDuration, class Rep, class Period&gt;
  constexpr ToDuration duration_cast(const duration&lt;Rep, Period&gt;&amp; d);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This operator shall not participate in overload resolution
unless <code>ToDuration</code> is  <del>an instantiation</del>
<ins>a specialization</ins> of <code>duration</code>.
</p>
</blockquote>

</blockquote>
</blockquote>
</li>

<li>
<p>
Modify 20.12.6.7 <code>time_point_cast</code> [time.point.cast]:
</p>

<blockquote>
<pre>
template &lt;class ToDuration, class Clock, class Duration&gt;
  constexpr time_point&lt;Clock, ToDuration&gt;
  time_point_cast(const time_point&lt;Clock, Duration&gt;&amp; t);
</pre>
<blockquote>
<p>
<i>Remarks:</i> This operator shall not participate in overload resolution
unless <code>ToDuration</code> is  <del>an instantiation</del>
<ins>a specialization</ins> of <code>duration</code>.
</p>
</blockquote>

</blockquote>
</blockquote>
</li>

</ul>


</body>
</html>
