Date: Tue, 06 Oct 1998 16:43:08 +0100 From: Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> I suggest to add the following three functions. xtime_diff and xtime_add do not always report the correct answer; they 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). * xtime_cmp(xtime_add(t, d), t) * 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.