Hi Paul, This formula in xtime.h caught my attention:
xtime_sec (xtime_t t) { return (t < 0 ? (t + XTIME_PRECISION - 1) / XTIME_PRECISION - 1 : xtime_nonnegative_sec (t)); } Let's look at its behaviour for t < 0. It looks wrong for two reasons: 1) This function is supposed to be constant on intervals of length XTIME_PRECISION - 1. However, it is also constant on the interval [ -2*XTIME_PRECISION+2 , -1 ], which is nearly twice as long. 2) For all integral t, the equation t = XTIME_PRECISION * (t / XTIME_PRECISION) + (t % XTIME_PRECISION) holds. For negative t, the function xtime_nsec (xtime_t t) { long int ns = t % XTIME_PRECISION; if (ns < 0) ns += XTIME_PRECISION; return ns; } applies a positive correction to the second summand in more than 99% of the cases. To compensate, a negative correction of the first summand should occur in more than 99% of the cases. But the formula (t + XTIME_PRECISION - 1) / XTIME_PRECISION - 1 applies a negative correction only in less than 1% of the cases. Here's a suggested fix. And a simplification in xtime_make. 2019-12-22 Bruno Haible <br...@clisp.org> gethrxtime: Fix a bug in xtime_sec(). * lib/xtime.h (xtime_make): Simplify. (xtime_sec): Fix an off-by-one error in 99.9999998% of the negative t cases. diff --git a/lib/xtime.h b/lib/xtime.h index 77f1c30..5e0ae89 100644 --- a/lib/xtime.h +++ b/lib/xtime.h @@ -42,12 +42,13 @@ extern "C" { XTIME_INLINE xtime_t xtime_make (xtime_t s, long int ns) { - const long int giga = 1000 * 1000 * 1000; - s += ns / giga; - ns %= giga; return XTIME_PRECISION * s + ns; } +/* The following functions split an extended time value: + T = XTIME_PRECISION * xtime_sec (T) + xtime_nsec (T) + with 0 <= xtime_nsec (T) < XTIME_PRECISION. */ + /* Return the number of seconds in T, which must be nonnegative. */ XTIME_INLINE xtime_t xtime_nonnegative_sec (xtime_t t) @@ -60,7 +61,7 @@ XTIME_INLINE xtime_t xtime_sec (xtime_t t) { return (t < 0 - ? (t + XTIME_PRECISION - 1) / XTIME_PRECISION - 1 + ? (t + 1) / XTIME_PRECISION - 1 : xtime_nonnegative_sec (t)); }