Refactor pytime.c

Move code to convert double timestamp to subfunctions.
This commit is contained in:
Victor Stinner 2015-09-02 00:49:16 +02:00
parent 799b05b052
commit 53e137c8dd
1 changed files with 67 additions and 50 deletions

View File

@ -60,44 +60,52 @@ _PyLong_FromTime_t(time_t t)
#endif #endif
} }
static int
_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
double denominator, _PyTime_round_t round)
{
double intpart, err;
/* volatile avoids unsafe optimization on float enabled by gcc -O3 */
volatile double floatpart;
floatpart = modf(d, &intpart);
if (floatpart < 0) {
floatpart = 1.0 + floatpart;
intpart -= 1.0;
}
floatpart *= denominator;
if (round == _PyTime_ROUND_CEILING) {
floatpart = ceil(floatpart);
if (floatpart >= denominator) {
floatpart = 0.0;
intpart += 1.0;
}
}
else {
floatpart = floor(floatpart);
}
*sec = (time_t)intpart;
err = intpart - (double)*sec;
if (err <= -1.0 || err >= 1.0) {
error_time_t_overflow();
return -1;
}
*numerator = (long)floatpart;
return 0;
}
static int static int
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
double denominator, _PyTime_round_t round) double denominator, _PyTime_round_t round)
{ {
assert(denominator <= LONG_MAX); assert(denominator <= LONG_MAX);
if (PyFloat_Check(obj)) { if (PyFloat_Check(obj)) {
double d, intpart, err; double d = PyFloat_AsDouble(obj);
/* volatile avoids unsafe optimization on float enabled by gcc -O3 */ return _PyTime_DoubleToDenominator(d, sec, numerator,
volatile double floatpart; denominator, round);
d = PyFloat_AsDouble(obj);
floatpart = modf(d, &intpart);
if (floatpart < 0) {
floatpart = 1.0 + floatpart;
intpart -= 1.0;
}
floatpart *= denominator;
if (round == _PyTime_ROUND_CEILING) {
floatpart = ceil(floatpart);
if (floatpart >= denominator) {
floatpart = 0.0;
intpart += 1.0;
}
}
else {
floatpart = floor(floatpart);
}
*sec = (time_t)intpart;
err = intpart - (double)*sec;
if (err <= -1.0 || err >= 1.0) {
error_time_t_overflow();
return -1;
}
*numerator = (long)floatpart;
return 0;
} }
else { else {
*sec = _PyLong_AsTime_t(obj); *sec = _PyLong_AsTime_t(obj);
@ -220,30 +228,39 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
} }
#endif #endif
static int
_PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round,
long to_nanoseconds)
{
/* volatile avoids unsafe optimization on float enabled by gcc -O3 */
volatile double d, err;
/* convert to a number of nanoseconds */
d = value;
d *= to_nanoseconds;
if (round == _PyTime_ROUND_CEILING)
d = ceil(d);
else
d = floor(d);
*t = (_PyTime_t)d;
err = d - (double)*t;
if (fabs(err) >= 1.0) {
_PyTime_overflow();
return -1;
}
return 0;
}
static int static int
_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
long to_nanoseconds) long to_nanoseconds)
{ {
if (PyFloat_Check(obj)) { if (PyFloat_Check(obj)) {
/* volatile avoids unsafe optimization on float enabled by gcc -O3 */ double d;
volatile double d, err;
/* convert to a number of nanoseconds */
d = PyFloat_AsDouble(obj); d = PyFloat_AsDouble(obj);
d *= to_nanoseconds; return _PyTime_FromFloatObject(t, d, round, to_nanoseconds);
if (round == _PyTime_ROUND_CEILING)
d = ceil(d);
else
d = floor(d);
*t = (_PyTime_t)d;
err = d - (double)*t;
if (fabs(err) >= 1.0) {
_PyTime_overflow();
return -1;
}
return 0;
} }
else { else {
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG