Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r86798 - in trunk: boost/chrono libs/chrono/test libs/chrono/test/duration
From: vicente.botet_at_[hidden]
Date: 2013-11-23 09:50:58


Author: viboes
Date: 2013-11-23 09:50:58 EST (Sat, 23 Nov 2013)
New Revision: 86798
URL: http://svn.boost.org/trac/boost/changeset/86798

Log:
Chrono: fix floor/round issues on negative numbers.

Added:
   trunk/libs/chrono/test/duration/rounding_pass.cpp (contents, props changed)
Text files modified:
   trunk/boost/chrono/floor.hpp | 4 +
   trunk/boost/chrono/round.hpp | 24 +++++---
   trunk/libs/chrono/test/Jamfile.v2 | 3
   trunk/libs/chrono/test/duration/rounding_pass.cpp | 104 ++++++++++++++++++++++++++++++++++++++++
   4 files changed, 123 insertions(+), 12 deletions(-)

Modified: trunk/boost/chrono/floor.hpp
==============================================================================
--- trunk/boost/chrono/floor.hpp Sat Nov 23 09:23:45 2013 (r86797)
+++ trunk/boost/chrono/floor.hpp 2013-11-23 09:50:58 EST (Sat, 23 Nov 2013) (r86798)
@@ -24,7 +24,9 @@
     template <class To, class Rep, class Period>
     To floor(const duration<Rep, Period>& d)
     {
- return duration_cast<To>(d);
+ To t = duration_cast<To>(d);
+ if (t>d) --t;
+ return t;
     }
 
 

Modified: trunk/boost/chrono/round.hpp
==============================================================================
--- trunk/boost/chrono/round.hpp Sat Nov 23 09:23:45 2013 (r86797)
+++ trunk/boost/chrono/round.hpp 2013-11-23 09:50:58 EST (Sat, 23 Nov 2013) (r86798)
@@ -26,18 +26,22 @@
     template <class To, class Rep, class Period>
     To round(const duration<Rep, Period>& d)
     {
+ typedef typename common_type<To, duration<Rep, Period> >::type result_type;
+ result_type diff0;
+ result_type diff1;
+
         To t0 = duration_cast<To>(d);
         To t1 = t0;
- ++t1;
-#if 0
- // Avoid the user of BOOST_AUTO to make the library portable to Sun, PGI, ..
- BOOST_AUTO(diff0, d - t0);
- BOOST_AUTO(diff1, t1 - d);
-#else
- typedef typename common_type<To, duration<Rep, Period> >::type result_type;
- result_type diff0 = d - t0;
- result_type diff1 = t1 - d;
-#endif
+ if (t0>d) {
+ --t1;
+ diff0 = t0 - d;
+ diff1 = d - t1;
+ } else {
+ ++t1;
+ diff0 = d - t0;
+ diff1 = t1 - d;
+ }
+
         if (diff0 == diff1)
         {
             if (t0.count() & 1)

Modified: trunk/libs/chrono/test/Jamfile.v2
==============================================================================
--- trunk/libs/chrono/test/Jamfile.v2 Sat Nov 23 09:23:45 2013 (r86797)
+++ trunk/libs/chrono/test/Jamfile.v2 2013-11-23 09:50:58 EST (Sat, 23 Nov 2013) (r86798)
@@ -432,6 +432,7 @@
         [ compile-fail duration/nonmember/times_rep2_lhs_fail.cpp ]
         [ compile-fail duration/nonmember/times_rep2_rhs_fail.cpp ]
         [ chrono-run-header duration/duration_values_pass.cpp ]
+ [ chrono-run-header duration/rounding_pass.cpp ]
         ;
 
     test-suite "time_point"
@@ -519,6 +520,6 @@
     test-suite ts_
         :
         #[ chrono-run test_7868.cpp ]
- [ chrono-run test_9337.cpp ]
+ #[ chrono-run test_9337.cpp ]
         ;
 

Added: trunk/libs/chrono/test/duration/rounding_pass.cpp
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ trunk/libs/chrono/test/duration/rounding_pass.cpp 2013-11-23 09:50:58 EST (Sat, 23 Nov 2013) (r86798)
@@ -0,0 +1,104 @@
+// Copyright 2013 Krzysztof Czainski
+// Copyright 2013 Vicente J. Botet Escriba
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+/*
+ * @file chrono_rounding.cpp
+ *
+ * @since 2013-11-22
+ * @author Krzysztof Czainski <1czajnik_at_[hidden]>
+ */
+
+#include <iostream>
+#include <boost/chrono/ceil.hpp>
+#include <boost/chrono/floor.hpp>
+#include <boost/chrono/round.hpp>
+
+#include <boost/chrono/chrono_io.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+using namespace boost::chrono;
+
+void test_floor()
+{
+ BOOST_TEST_EQ( seconds(-2), floor<seconds>( milliseconds(-2000) ) );
+ BOOST_TEST_EQ( seconds(-2), floor<seconds>( milliseconds(-1999) ) );
+ BOOST_TEST_EQ( seconds(-2), floor<seconds>( milliseconds(-1001) ) );
+ BOOST_TEST_EQ( seconds(-1), floor<seconds>( milliseconds(-1000) ) );
+ BOOST_TEST_EQ( seconds(-1), floor<seconds>( milliseconds(-999) ) );
+ BOOST_TEST_EQ( seconds(-1), floor<seconds>( milliseconds(-1) ) );
+ BOOST_TEST_EQ( seconds(0), floor<seconds>( milliseconds(0) ) );
+ BOOST_TEST_EQ( seconds(0), floor<seconds>( milliseconds(1) ) );
+ BOOST_TEST_EQ( seconds(0), floor<seconds>( milliseconds(999) ) );
+ BOOST_TEST_EQ( seconds(1), floor<seconds>( milliseconds(1000) ) );
+ BOOST_TEST_EQ( seconds(1), floor<seconds>( milliseconds(1001) ) );
+ BOOST_TEST_EQ( seconds(1), floor<seconds>( milliseconds(1999) ) );
+ BOOST_TEST_EQ( seconds(2), floor<seconds>( milliseconds(2000) ) );
+ {
+ // check that int32 isn't overflowed in intermediate calculations:
+ typedef duration<int32_t> sec32;
+ typedef duration< int32_t, boost::ratio<999,1000> > sec32_m1ms;
+ BOOST_TEST_EQ( sec32(-999000000), floor<sec32>( sec32_m1ms(-1000000000) ) );
+ BOOST_TEST_EQ( sec32( 999000000), floor<sec32>( sec32_m1ms( 1000000000) ) );
+ }
+}
+
+void test_ceil()
+{
+ BOOST_TEST_EQ( seconds(-2), ceil<seconds>( milliseconds(-2000) ) );
+ BOOST_TEST_EQ( seconds(-1), ceil<seconds>( milliseconds(-1999) ) );
+ BOOST_TEST_EQ( seconds(-1), ceil<seconds>( milliseconds(-1001) ) );
+ BOOST_TEST_EQ( seconds(-1), ceil<seconds>( milliseconds(-1000) ) );
+ BOOST_TEST_EQ( seconds(0), ceil<seconds>( milliseconds(-999) ) );
+ BOOST_TEST_EQ( seconds(0), ceil<seconds>( milliseconds(-1) ) );
+ BOOST_TEST_EQ( seconds(0), ceil<seconds>( milliseconds(0) ) );
+ BOOST_TEST_EQ( seconds(1), ceil<seconds>( milliseconds(1) ) );
+ BOOST_TEST_EQ( seconds(1), ceil<seconds>( milliseconds(999) ) );
+ BOOST_TEST_EQ( seconds(1), ceil<seconds>( milliseconds(1000) ) );
+ BOOST_TEST_EQ( seconds(2), ceil<seconds>( milliseconds(1001) ) );
+ BOOST_TEST_EQ( seconds(2), ceil<seconds>( milliseconds(1999) ) );
+ BOOST_TEST_EQ( seconds(2), ceil<seconds>( milliseconds(2000) ) );
+ {
+ // check that int32 isn't overflowed in intermediate calculations:
+ typedef duration<int32_t> sec32;
+ typedef duration< int32_t, boost::ratio<999,1000> > sec32_m1ms;
+ BOOST_TEST_EQ( sec32(-999000000), ceil<sec32>( sec32_m1ms(-1000000000) ) );
+ BOOST_TEST_EQ( sec32( 999000000), ceil<sec32>( sec32_m1ms( 1000000000) ) );
+ }
+}
+
+void test_round()
+{
+ // to even on tie
+ BOOST_TEST_EQ( seconds(-2), round<seconds>( milliseconds(-2000) ) );
+ BOOST_TEST_EQ( seconds(-2), round<seconds>( milliseconds(-1500) ) );
+ BOOST_TEST_EQ( seconds(-1), round<seconds>( milliseconds(-1499) ) );
+ BOOST_TEST_EQ( seconds(-1), round<seconds>( milliseconds(-1000) ) );
+ BOOST_TEST_EQ( seconds(0), round<seconds>( milliseconds(-500) ) );
+ BOOST_TEST_EQ( seconds(0), round<seconds>( milliseconds(-499) ) );
+ BOOST_TEST_EQ( seconds(0), round<seconds>( milliseconds(0) ) );
+ BOOST_TEST_EQ( seconds(0), round<seconds>( milliseconds(499) ) );
+ BOOST_TEST_EQ( seconds(0), round<seconds>( milliseconds(500) ) );
+ BOOST_TEST_EQ( seconds(1), round<seconds>( milliseconds(1000) ) );
+ BOOST_TEST_EQ( seconds(1), round<seconds>( milliseconds(1499) ) );
+ BOOST_TEST_EQ( seconds(2), round<seconds>( milliseconds(1500) ) );
+ BOOST_TEST_EQ( seconds(2), round<seconds>( milliseconds(2000) ) );
+ {
+ // check that int32 isn't overflowed in intermediate calculations:
+ typedef duration<int32_t> sec32;
+ typedef duration< int32_t, boost::ratio<999,1000> > sec32_m1ms;
+ BOOST_TEST_EQ( sec32(-999000000), round<sec32>( sec32_m1ms(-1000000000) ) );
+ BOOST_TEST_EQ( sec32( 999000000), round<sec32>( sec32_m1ms( 1000000000) ) );
+ }
+}
+
+int main()
+{
+ test_floor();
+ test_ceil();
+ test_round();
+ return boost::report_errors();
+
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk