Merge pull request #3 from HowardHinnant/master

update from mainstream repo
This commit is contained in:
Ivan Pizhenko 2015-11-29 00:01:48 +02:00
commit 636e094901

127
date.h
View File

@ -796,14 +796,76 @@ public:
{}
};
// truncate towards zero
namespace detail
{
template <class T>
struct choose_trunc_type
{
static const int digits = std::numeric_limits<T>::digits;
using type = typename std::conditional
<
digits < 32,
std::int32_t,
typename std::conditional
<
digits < 64,
std::int64_t,
#ifdef __SIZEOF_INT128__
__int128
#else
std::int64_t
#endif
>::type
>::type;
};
template <class T>
CONSTCD11
inline
typename std::enable_if
<
!std::chrono::treat_as_floating_point<T>::value,
T
>::type
trunc(T t) noexcept
{
return t;
}
template <class T>
CONSTCD14
inline
typename std::enable_if
<
std::chrono::treat_as_floating_point<T>::value,
T
>::type
trunc(T t) noexcept
{
using namespace std;
using I = typename choose_trunc_type<T>::type;
CONSTDATA auto digits = numeric_limits<T>::digits;
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
static_assert(digits < numeric_limits<I>::digits, "");
#endif
CONSTDATA auto max = I{1} << (digits-1);
CONSTDATA auto min = -max;
if (min <= t && t <= max && t != 0 && t == t)
t = static_cast<T>(static_cast<I>(t));
return t;
}
} // detail
// trunc towards zero
template <class To, class Rep, class Period>
CONSTCD11
inline
To
truncate(const std::chrono::duration<Rep, Period>& d)
trunc(const std::chrono::duration<Rep, Period>& d)
{
return std::chrono::duration_cast<To>(d);
return To{detail::trunc(std::chrono::duration_cast<To>(d).count())};
}
// round down
@ -813,9 +875,9 @@ inline
To
floor(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
auto t = trunc<To>(d);
if (t > d)
t = t - To{1};
return t - To{1};
return t;
}
@ -826,17 +888,17 @@ inline
To
round(const std::chrono::duration<Rep, Period>& d)
{
To t0 = floor<To>(d);
To t1 = t0 + To{1};
auto t0 = floor<To>(d);
auto t1 = t0 + To{1};
auto diff0 = d - t0;
auto diff1 = t1 - d;
if (diff0 == diff1)
{
if (t0.count() & 1)
return t1;
return t0;
if (t0 - trunc<To>(t0/2)*2 == To{0})
return t0;
return t1;
}
else if (diff0 < diff1)
if (diff0 < diff1)
return t0;
return t1;
}
@ -848,20 +910,33 @@ inline
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
auto t = trunc<To>(d);
if (t < d)
t = t + To{1};
return t + To{1};
return t;
}
// truncate towards zero
template <class Rep, class Period,
class = typename std::enable_if
<
std::numeric_limits<Rep>::is_signed
>::type>
CONSTCD11
std::chrono::duration<Rep, Period>
abs(std::chrono::duration<Rep, Period> d)
{
return d >= d.zero() ? d : -d;
}
// trunc towards zero
template <class To, class Clock, class FromDuration>
CONSTCD11
inline
std::chrono::time_point<Clock, To>
truncate(const std::chrono::time_point<Clock, FromDuration>& tp)
trunc(const std::chrono::time_point<Clock, FromDuration>& tp)
{
return std::chrono::time_point_cast<To>(tp);
using std::chrono::time_point;
return time_point<Clock, To>{trunc<To>(tp.time_since_epoch())};
}
// round down
@ -3278,9 +3353,9 @@ public:
os.flags(std::ios::dec | std::ios::right);
if (t.mode_ != am && t.mode_ != pm)
os.width(2);
os << abs(t.h_.count()) << ':';
os << std::abs(t.h_.count()) << ':';
os.width(2);
os << abs(t.m_.count());
os << std::abs(t.m_.count());
switch (t.mode_)
{
case am:
@ -3349,11 +3424,11 @@ public:
os.flags(std::ios::dec | std::ios::right);
if (t.mode_ != am && t.mode_ != pm)
os.width(2);
os << abs(t.h_.count()) << ':';
os << std::abs(t.h_.count()) << ':';
os.width(2);
os << abs(t.m_.count()) << ':';
os << std::abs(t.m_.count()) << ':';
os.width(2);
os << abs(t.s_.count());
os << std::abs(t.s_.count());
switch (t.mode_)
{
case am:
@ -3429,22 +3504,22 @@ public:
os.flags(std::ios::dec | std::ios::right);
if (t.mode_ != am && t.mode_ != pm)
os.width(2);
os << abs(t.h_.count()) << ':';
os << std::abs(t.h_.count()) << ':';
os.width(2);
os << abs(t.m_.count()) << ':';
os << std::abs(t.m_.count()) << ':';
os.width(2);
os << abs(t.s_.count()) << '.';
os << std::abs(t.s_.count()) << '.';
#if __cplusplus >= 201402
CONSTDATA auto cl10 = ceil_log10(Period::den);
using scale = std::ratio_multiply<Period, std::ratio<pow10(cl10)>>;
os.width(cl10);
os << abs(t.sub_s_.count()) * scale::num / scale::den;
os << std::abs(t.sub_s_.count()) * scale::num / scale::den;
#else // __cplusplus >= 201402
// inefficient sub-optimal run-time mess, but gets the job done
const unsigned long long cl10 = std::ceil(log10(Period::den));
const auto p10 = std::pow(10., cl10);
os.width(cl10);
os << static_cast<unsigned long long>(abs(t.sub_s_.count())
os << static_cast<unsigned long long>(std::abs(t.sub_s_.count())
* Period::num * p10 / Period::den);
#endif // __cplusplus >= 201402
switch (t.mode_)