$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
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();
+
+}