Issue #22117: Remove _PyTime_ROUND_DOWN and _PyTime_ROUND_UP rounding methods

Use _PyTime_ROUND_FLOOR and _PyTime_ROUND_CEILING instead.
This commit is contained in:
Victor Stinner 2015-03-30 03:57:14 +02:00
parent 869e1778c0
commit a695f83f0d
4 changed files with 20 additions and 110 deletions

View File

@ -25,14 +25,9 @@ typedef PY_INT64_T _PyTime_t;
#endif #endif
typedef enum { typedef enum {
/* Round towards zero. */
_PyTime_ROUND_DOWN=0,
/* Round away from zero.
For example, used for timeout to wait "at least" N seconds. */
_PyTime_ROUND_UP,
/* Round towards minus infinity (-inf). /* Round towards minus infinity (-inf).
For example, used to read a clock. */ For example, used to read a clock. */
_PyTime_ROUND_FLOOR, _PyTime_ROUND_FLOOR=0,
/* Round towards infinity (+inf). /* Round towards infinity (+inf).
For example, used for timeout to wait "at least" N seconds. */ For example, used for timeout to wait "at least" N seconds. */
_PyTime_ROUND_CEILING _PyTime_ROUND_CEILING

View File

@ -24,20 +24,12 @@ TIME_MINYEAR = -TIME_MAXYEAR - 1
SEC_TO_NS = 10 ** 9 SEC_TO_NS = 10 ** 9
class _PyTime(enum.IntEnum): class _PyTime(enum.IntEnum):
# Round towards zero
ROUND_DOWN = 0
# Round away from zero
ROUND_UP = 1
# Round towards minus infinity (-inf) # Round towards minus infinity (-inf)
ROUND_FLOOR = 2 ROUND_FLOOR = 0
# Round towards infinity (+inf) # Round towards infinity (+inf)
ROUND_CEILING = 3 ROUND_CEILING = 1
ALL_ROUNDING_METHODS = ( ALL_ROUNDING_METHODS = (_PyTime.ROUND_FLOOR, _PyTime.ROUND_CEILING)
_PyTime.ROUND_UP,
_PyTime.ROUND_DOWN,
_PyTime.ROUND_FLOOR,
_PyTime.ROUND_CEILING)
class TimeTestCase(unittest.TestCase): class TimeTestCase(unittest.TestCase):
@ -617,13 +609,6 @@ class TestPytime(unittest.TestCase):
def test_time_t(self): def test_time_t(self):
from _testcapi import pytime_object_to_time_t from _testcapi import pytime_object_to_time_t
for obj, time_t, rnd in ( for obj, time_t, rnd in (
# Round towards zero
(0, 0, _PyTime.ROUND_DOWN),
(-1, -1, _PyTime.ROUND_DOWN),
(-1.0, -1, _PyTime.ROUND_DOWN),
(-1.9, -1, _PyTime.ROUND_DOWN),
(1.0, 1, _PyTime.ROUND_DOWN),
(1.9, 1, _PyTime.ROUND_DOWN),
# Round towards minus infinity (-inf) # Round towards minus infinity (-inf)
(0, 0, _PyTime.ROUND_FLOOR), (0, 0, _PyTime.ROUND_FLOOR),
(-1, -1, _PyTime.ROUND_FLOOR), (-1, -1, _PyTime.ROUND_FLOOR),
@ -631,13 +616,6 @@ class TestPytime(unittest.TestCase):
(-1.9, -2, _PyTime.ROUND_FLOOR), (-1.9, -2, _PyTime.ROUND_FLOOR),
(1.0, 1, _PyTime.ROUND_FLOOR), (1.0, 1, _PyTime.ROUND_FLOOR),
(1.9, 1, _PyTime.ROUND_FLOOR), (1.9, 1, _PyTime.ROUND_FLOOR),
# Round away from zero
(0, 0, _PyTime.ROUND_UP),
(-1, -1, _PyTime.ROUND_UP),
(-1.0, -1, _PyTime.ROUND_UP),
(-1.9, -2, _PyTime.ROUND_UP),
(1.0, 1, _PyTime.ROUND_UP),
(1.9, 2, _PyTime.ROUND_UP),
# Round towards infinity (+inf) # Round towards infinity (+inf)
(0, 0, _PyTime.ROUND_CEILING), (0, 0, _PyTime.ROUND_CEILING),
(-1, -1, _PyTime.ROUND_CEILING), (-1, -1, _PyTime.ROUND_CEILING),
@ -657,20 +635,6 @@ class TestPytime(unittest.TestCase):
def test_timespec(self): def test_timespec(self):
from _testcapi import pytime_object_to_timespec from _testcapi import pytime_object_to_timespec
for obj, timespec, rnd in ( for obj, timespec, rnd in (
# Round towards zero
(0, (0, 0), _PyTime.ROUND_DOWN),
(-1, (-1, 0), _PyTime.ROUND_DOWN),
(-1.0, (-1, 0), _PyTime.ROUND_DOWN),
(1e-9, (0, 1), _PyTime.ROUND_DOWN),
(1e-10, (0, 0), _PyTime.ROUND_DOWN),
(-1e-9, (-1, 999999999), _PyTime.ROUND_DOWN),
(-1e-10, (0, 0), _PyTime.ROUND_DOWN),
(-1.2, (-2, 800000000), _PyTime.ROUND_DOWN),
(0.9999999999, (0, 999999999), _PyTime.ROUND_DOWN),
(1.1234567890, (1, 123456789), _PyTime.ROUND_DOWN),
(1.1234567899, (1, 123456789), _PyTime.ROUND_DOWN),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_DOWN),
(-1.1234567891, (-2, 876543211), _PyTime.ROUND_DOWN),
# Round towards minus infinity (-inf) # Round towards minus infinity (-inf)
(0, (0, 0), _PyTime.ROUND_FLOOR), (0, (0, 0), _PyTime.ROUND_FLOOR),
(-1, (-1, 0), _PyTime.ROUND_FLOOR), (-1, (-1, 0), _PyTime.ROUND_FLOOR),
@ -685,20 +649,6 @@ class TestPytime(unittest.TestCase):
(1.1234567899, (1, 123456789), _PyTime.ROUND_FLOOR), (1.1234567899, (1, 123456789), _PyTime.ROUND_FLOOR),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_FLOOR), (-1.1234567890, (-2, 876543211), _PyTime.ROUND_FLOOR),
(-1.1234567891, (-2, 876543210), _PyTime.ROUND_FLOOR), (-1.1234567891, (-2, 876543210), _PyTime.ROUND_FLOOR),
# Round away from zero
(0, (0, 0), _PyTime.ROUND_UP),
(-1, (-1, 0), _PyTime.ROUND_UP),
(-1.0, (-1, 0), _PyTime.ROUND_UP),
(1e-9, (0, 1), _PyTime.ROUND_UP),
(1e-10, (0, 1), _PyTime.ROUND_UP),
(-1e-9, (-1, 999999999), _PyTime.ROUND_UP),
(-1e-10, (-1, 999999999), _PyTime.ROUND_UP),
(-1.2, (-2, 800000000), _PyTime.ROUND_UP),
(0.9999999999, (1, 0), _PyTime.ROUND_UP),
(1.1234567890, (1, 123456790), _PyTime.ROUND_UP),
(1.1234567899, (1, 123456790), _PyTime.ROUND_UP),
(-1.1234567890, (-2, 876543211), _PyTime.ROUND_UP),
(-1.1234567891, (-2, 876543210), _PyTime.ROUND_UP),
# Round towards infinity (+inf) # Round towards infinity (+inf)
(0, (0, 0), _PyTime.ROUND_CEILING), (0, (0, 0), _PyTime.ROUND_CEILING),
(-1, (-1, 0), _PyTime.ROUND_CEILING), (-1, (-1, 0), _PyTime.ROUND_CEILING),
@ -836,40 +786,26 @@ class TestPyTime_t(unittest.TestCase):
PyTime_FromSecondsObject(-9223372037.0, rnd) PyTime_FromSecondsObject(-9223372037.0, rnd)
# Conversion giving different results depending on the rounding method # Conversion giving different results depending on the rounding method
UP = _PyTime.ROUND_UP
DOWN = _PyTime.ROUND_DOWN
FLOOR = _PyTime.ROUND_FLOOR FLOOR = _PyTime.ROUND_FLOOR
CEILING = _PyTime.ROUND_CEILING CEILING = _PyTime.ROUND_CEILING
for obj, ts, rnd in ( for obj, ts, rnd in (
# close to zero # close to zero
( 1e-10, 1, CEILING),
( 1e-10, 1, UP),
( 1e-10, 0, DOWN),
( 1e-10, 0, FLOOR), ( 1e-10, 0, FLOOR),
(-1e-10, 0, CEILING), ( 1e-10, 1, CEILING),
(-1e-10, 0, DOWN),
(-1e-10, -1, UP),
(-1e-10, -1, FLOOR), (-1e-10, -1, FLOOR),
(-1e-10, 0, CEILING),
# test rounding of the last nanosecond # test rounding of the last nanosecond
( 1.1234567899, 1123456790, CEILING),
( 1.1234567899, 1123456790, UP),
( 1.1234567899, 1123456789, DOWN),
( 1.1234567899, 1123456789, FLOOR), ( 1.1234567899, 1123456789, FLOOR),
(-1.1234567899, -1123456789, CEILING), ( 1.1234567899, 1123456790, CEILING),
(-1.1234567899, -1123456789, DOWN),
(-1.1234567899, -1123456790, UP),
(-1.1234567899, -1123456790, FLOOR), (-1.1234567899, -1123456790, FLOOR),
(-1.1234567899, -1123456789, CEILING),
# close to 1 second # close to 1 second
( 0.9999999999, 1000000000, CEILING),
( 0.9999999999, 1000000000, UP),
( 0.9999999999, 999999999, DOWN),
( 0.9999999999, 999999999, FLOOR), ( 0.9999999999, 999999999, FLOOR),
(-0.9999999999, -999999999, CEILING), ( 0.9999999999, 1000000000, CEILING),
(-0.9999999999, -999999999, DOWN),
(-0.9999999999, -1000000000, UP),
(-0.9999999999, -1000000000, FLOOR), (-0.9999999999, -1000000000, FLOOR),
(-0.9999999999, -999999999, CEILING),
): ):
with self.subTest(obj=obj, round=rnd, timestamp=ts): with self.subTest(obj=obj, round=rnd, timestamp=ts):
self.assertEqual(PyTime_FromSecondsObject(obj, rnd), ts) self.assertEqual(PyTime_FromSecondsObject(obj, rnd), ts)
@ -939,30 +875,20 @@ class TestPyTime_t(unittest.TestCase):
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd): with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
self.assertEqual(PyTime_AsTimeval(ns, rnd), tv) self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)
UP = _PyTime.ROUND_UP
DOWN = _PyTime.ROUND_DOWN
FLOOR = _PyTime.ROUND_FLOOR FLOOR = _PyTime.ROUND_FLOOR
CEILING = _PyTime.ROUND_CEILING CEILING = _PyTime.ROUND_CEILING
for ns, tv, rnd in ( for ns, tv, rnd in (
# nanoseconds # nanoseconds
(1, (0, 1), CEILING),
(1, (0, 1), UP),
(1, (0, 0), DOWN),
(1, (0, 0), FLOOR), (1, (0, 0), FLOOR),
(-1, (0, 0), CEILING), (1, (0, 1), CEILING),
(-1, (0, 0), DOWN),
(-1, (-1, 999999), UP),
(-1, (-1, 999999), FLOOR), (-1, (-1, 999999), FLOOR),
(-1, (0, 0), CEILING),
# seconds + nanoseconds # seconds + nanoseconds
(1234567001, (1, 234568), CEILING),
(1234567001, (1, 234568), UP),
(1234567001, (1, 234567), DOWN),
(1234567001, (1, 234567), FLOOR), (1234567001, (1, 234567), FLOOR),
(-1234567001, (-2, 765433), CEILING), (1234567001, (1, 234568), CEILING),
(-1234567001, (-2, 765433), DOWN),
(-1234567001, (-2, 765432), UP),
(-1234567001, (-2, 765432), FLOOR), (-1234567001, (-2, 765432), FLOOR),
(-1234567001, (-2, 765433), CEILING),
): ):
with self.subTest(nanoseconds=ns, timeval=tv, round=rnd): with self.subTest(nanoseconds=ns, timeval=tv, round=rnd):
self.assertEqual(PyTime_AsTimeval(ns, rnd), tv) self.assertEqual(PyTime_AsTimeval(ns, rnd), tv)

View File

@ -2634,8 +2634,7 @@ run_in_subinterp(PyObject *self, PyObject *args)
static int static int
check_time_rounding(int round) check_time_rounding(int round)
{ {
if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP if (round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) {
&& round != _PyTime_ROUND_FLOOR && round != _PyTime_ROUND_CEILING) {
PyErr_SetString(PyExc_ValueError, "invalid rounding"); PyErr_SetString(PyExc_ValueError, "invalid rounding");
return -1; return -1;
} }

View File

@ -26,16 +26,6 @@ error_time_t_overflow(void)
"timestamp out of range for platform time_t"); "timestamp out of range for platform time_t");
} }
static int
_PyTime_RoundTowardsPosInf(int is_neg, _PyTime_round_t round)
{
if (round == _PyTime_ROUND_FLOOR)
return 0;
if (round == _PyTime_ROUND_CEILING)
return 1;
return ((round == _PyTime_ROUND_UP) ^ is_neg);
}
time_t time_t
_PyLong_AsTime_t(PyObject *obj) _PyLong_AsTime_t(PyObject *obj)
{ {
@ -84,7 +74,7 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
} }
floatpart *= denominator; floatpart *= denominator;
if (_PyTime_RoundTowardsPosInf(intpart < 0, round)) { if (round == _PyTime_ROUND_CEILING) {
floatpart = ceil(floatpart); floatpart = ceil(floatpart);
if (floatpart >= denominator) { if (floatpart >= denominator) {
floatpart = 0.0; floatpart = 0.0;
@ -121,7 +111,7 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
double d, intpart, err; double d, intpart, err;
d = PyFloat_AsDouble(obj); d = PyFloat_AsDouble(obj);
if (_PyTime_RoundTowardsPosInf(d < 0, round)) if (round == _PyTime_ROUND_CEILING)
d = ceil(d); d = ceil(d);
else else
d = floor(d); d = floor(d);
@ -223,7 +213,7 @@ _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
d = PyFloat_AsDouble(obj); d = PyFloat_AsDouble(obj);
d *= 1e9; d *= 1e9;
if (_PyTime_RoundTowardsPosInf(d < 0, round)) if (round == _PyTime_ROUND_CEILING)
d = ceil(d); d = ceil(d);
else else
d = floor(d); d = floor(d);
@ -289,7 +279,7 @@ _PyTime_Multiply(_PyTime_t t, unsigned int multiply, _PyTime_round_t round)
_PyTime_t k; _PyTime_t k;
if (multiply < SEC_TO_NS) { if (multiply < SEC_TO_NS) {
k = SEC_TO_NS / multiply; k = SEC_TO_NS / multiply;
if (_PyTime_RoundTowardsPosInf(t < 0, round)) if (round == _PyTime_ROUND_CEILING)
return (t + k - 1) / k; return (t + k - 1) / k;
else else
return t / k; return t / k;
@ -350,7 +340,7 @@ _PyTime_AsTimeval_impl(_PyTime_t t, struct timeval *tv, _PyTime_round_t round,
res = -1; res = -1;
#endif #endif
if (_PyTime_RoundTowardsPosInf(tv->tv_sec < 0, round)) if (round == _PyTime_ROUND_CEILING)
tv->tv_usec = (int)((ns + US_TO_NS - 1) / US_TO_NS); tv->tv_usec = (int)((ns + US_TO_NS - 1) / US_TO_NS);
else else
tv->tv_usec = (int)(ns / US_TO_NS); tv->tv_usec = (int)(ns / US_TO_NS);