Paul Eggert eggert at twinsun.com
Wed Oct 7 09:50:06 UTC 1998

```   Date: Tue, 06 Oct 1998 16:43:08 +0100
From: Markus Kuhn <Markus.Kuhn at cl.cam.ac.uk>

I suggest to add the following three functions.

suffer from rounding errors.  This is inherent to the interface, at
least on the vast majority of hosts (e.g. hosts where `double' is IEEE
double-precision).  Applications that want to work reliably on all
timestamps will therefore have to avoid these primitives.

double xtime_diff(struct xtime t1, struct xtime t2)
...
return (t1.sec - t2.sec) + (t1.nsec - t2.nsec) / 1.0e9;

This implementation suffers from double-rounding, so the answer is not
always the closest to the true result.  An implementation should be
free to supply a more precise answer than the one implied by this
expression.

struct xtime xtime_add(struct xtime t, double d)
... double ds;...
t.nsec += floor(modf(d, &ds) * 1.0e9 + 0.5);
t.sec  += ds;

First, this also suffers from multiple-rounding problems.

Second, why is that `+ 0.5' there?  strfxtime is supposed to truncate
to minus infinity, so for consistency shouldn't conversion to floating
point also truncate to minus infinity?

Third, if we really want rounding instead of truncation, the
implementation should be free to round to even (instead of rounding to
minus infinity), as round-to-even is the IEEE floating-point default
and typically gives better answers in practice.

* Assertions:
*
* fabs(xtime_diff(xtime_add(t, d), t) - d) <= 0.5e-9
*   for all t, d with fabs(t.sec + d) < 2**62 and t.nsec in the valid range

I think this assertion is false in the presence of rounding (or
truncation) errors, but I haven't checked this.  There may also be
problems with floating-point overflow on weird implementations allowed
by the C standard; I haven't checked this either (this is not of
practical importance, but the C standards nerds will care).

*   is in the set {-1, 0, 1} and has the same sign as d or is 0 iff d==0.0

This assertion is false e.g. if d == 1e-10.

So many problems in what should be simple code!  I still say that
struct xtime is way too error-prone compared to integer timestamps.
If we used integer timestamps, we wouldn't need xtime_cmp, xtime_diff,
and xtime_add at all, as <, -, and + would do the job more efficiently
and more naturally.

This allows you to use time intervals such as 86400.0 in order to
mean "one day later" on the UTC clock, which is what most
applications need (and what POSIX provided so far).

This reinforces my previous suggestion that we should modify the spec
so that TIME_UTC clocks ignore leap seconds entirely.  This will make
the primitives operate more consistently, and will remove the need for
tricks like `if (t1.nsec > 1000000000) t1.nsec = 1000000000;' in user
code.

Has anyone made some experiments or can contribute arguments to decide
on whether passing 96-bit structs by pointer or by value is more desirable?

Has anyone completed the UTC part of the xtime_make() specification
code in the proposal or do I have to do this myself?

Is anyone willing to merge the xtime text with the existing C9X
draft and also include the change requests that Paul submitted
to ANSI?

All these are is on my list of things to do, though I'll be proposing
the TIME_UTC variant mentioned above, so it may not match exactly what
you want.

```