<!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: P0092R0<br>
<br/>
<br/>
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br/>
2015-09-23<br/>
</address>
<hr/>
<h1 align=center>Polishing <code>&lt;chrono&gt;</code></h1>

<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>
Increment and decrement operators for <code>time_point</code>.
</p></li>
<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 an instantiation of <code>duration</code>.
</p>
<p>
<i>Returns:</i> The largest result <code>t</code> representable in <code>ToDuration</code>
that can be returned from <code>duration_cast&lt;ToDuration&gt;(d)</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 an instantiation of <code>duration</code>.
</p>
<p>
<i>Returns:</i> The smallest result <code>t</code> representable in <code>ToDuration</code>
that can be returned from <code>duration_cast&lt;ToDuration&gt;(d)</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 an instantiation 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 result <code>t</code> representable in <code>ToDuration</code>
which is closest in value to <code>d</code>.  If <code>d</code> falls exactly half
way between <code>t</code> and an adjacent representable value in
<code>ToDuration</code>, then the value of <code>ToDuration</code> which is even is
returned.
</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>duration&lt;Rep, Period&gt;::min() &lt; duration&lt;Rep, Period&gt;::zero()</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 Class template <code>time_point</code> [time.point], in
the synopsis, in the section <i>arithmetic</i>:
</p>
<blockquote><pre>
time_point&amp; operator++();
time_point  operator++(int);
time_point&amp; operator--();
time_point  operator--(int);
</pre></blockquote>
</li>

<li>
<p>
Add to 20.12.6.3 <code>time_point</code> arithmetic [time.point.arithmetic]:
</p>
<blockquote>

<pre>
time_point&amp; operator++();
</pre>
<blockquote>
<p>
<i>Effects:</i> <code>++d_</code>.
</p>
<p>
<i>Returns:</i> <code>*this</code>.
</p>
</blockquote>

<pre>
time_point operator++(int);
</pre>
<blockquote>
<p>
<i>Returns:</i> <code>time_point(d_++)</code>.
</p>
</blockquote>

<pre>
time_point&amp; operator--();
</pre>
<blockquote>
<p>
<i>Effects:</i> <code>--d_</code>.
</p>
<p>
<i>Returns:</i> <code>*this</code>.
</p>
</blockquote>

<pre>
time_point operator--(int);
</pre>
<blockquote>
<p>
<i>Returns:</i> <code>time_point(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 an instantiation 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 an instantiation 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 an instantiation 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>

</ul>

</body>
</html>
