Yet another iteration on difftime.c. --ado /* ** This file is in the public domain, so clarified as of ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). */ #ifndef lint #ifndef NOID static char elsieid[] = "%W%"; #endif /* !defined NOID */ #endif /* !defined lint */ /*LINTLIBRARY*/ #include "sys/types.h" /* for time_t */ #include "private.h" /* for TYPE_INTEGRAL and TYPE_SIGNED */ double difftime(time1, time0) const time_t time1; const time_t time0; { /* ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract ** (assuming that the wider type has more precision). ** This is the common real-world case circa 2004. */ if (sizeof (double) > sizeof (time_t)) return (double) time1 - (double) time0; if (!TYPE_INTEGRAL(time_t)) { /* ** time_t is floating. */ return time1 - time0; } if (!TYPE_SIGNED(time_t)) { /* ** time_t is integral and unsigned. ** The difference of two unsigned values can't overflow ** if the minuend is greater than or equal to the subtrahend. */ if (time1 >= time0) return time1 - time0; else return -((double) (time0 - time1)); } /* ** time_t is integral and signed. ** Handle cases where both time1 and time0 have the same sign ** (meaning that their difference cannot overflow). */ if (time1 >= 0 && time0 >= 0 || time1 < 0 && time0 < 0) return time1 - time0; /* ** time1 and time0 have opposite signs. ** Punt if unsigned long is too narrow. */ if (sizeof (unsigned long) < sizeof (time_t)) return (double) time1 - (double) time0; /* ** Stay calm...decent optimizers will eliminate the complexity below. */ if (time1 >= 0 /* && time0 < 0 */) return (unsigned long) time1 + (unsigned long) (-(time0 + 1)) + 1; return -(double) ((unsigned long) time0 + (unsigned long) (-(time1 + 1)) + 1); }
"Olson, Arthur David (NIH/NCI)" <olsona@dc37a.nci.nih.gov> writes:
** If (sizeof (double) > sizeof (time_t)) simply convert and subtract ** (assuming that the wider type has more precision).
This should say "larger" rather than "wider". In C99 standardese, "larger" talks about sizeof, "wider" talks about useful bits (ie. precision).
if (time1 >= 0 && time0 >= 0 || time1 < 0 && time0 < 0)
It'd be nicer, shorter, and often faster to say this: if ((time1 < 0) == (time0 < 0)) and then, for symmetry (and more likelihood for compiler optimization) replace "time1 >= 0 /* && time0 < 0 */" with "time0 < 0 /* && time1 >= 0 */" later on.
** Punt if unsigned long is too narrow.
Why not use uintmax_t if 199901 <= __STDC_VERSION__? That will work on all hosts except the weird ones where unsigned values have holes. The implementation is still a bit slow for the common case where time_t is a signed integer type and fits in double (e.g., x86) or long double (e.g., x86-64). This case should be doable without any tests or branches. It's not a correctness issue; just a performance issue. I sense that you didn't like the version that I sent in, because of its complexity. What part of the complexity turned you off the most? Perhaps I could simplify that part.
Early this summer I had the occasion to visit the Mount Washington Observatory weather station atop (of course!) Mount Washington. During the short tour, I noticed that their clock was an hour behind, and I commented on it. One of the staff members said that the station was on Eastern Standard Time and didn't change their clocks for Daylight Saving. They refer to "station time" and "valley time". The staffer further said that officially speaking, you lose or gain an hour everytime you walk through that door (pointing to the exit) during the summer months. They said that they stay on standard time so that their reports will always have times which are 5 hours behind UTC. I doubt that this is of much interest here, but if anyone cares, they're on this list. Dave C. -- David A. Cantor Groton, CT 06340-3731 DCantor@shore.net
participants (3)
-
Dave Cantor -
Olson, Arthur David (NIH/NCI) -
Paul Eggert