14616d0f9Sopenharmony_ci/* Return the difference between two timestamps.  */
24616d0f9Sopenharmony_ci
34616d0f9Sopenharmony_ci/*
44616d0f9Sopenharmony_ci** This file is in the public domain, so clarified as of
54616d0f9Sopenharmony_ci** 1996-06-05 by Arthur David Olson.
64616d0f9Sopenharmony_ci*/
74616d0f9Sopenharmony_ci
84616d0f9Sopenharmony_ci/*LINTLIBRARY*/
94616d0f9Sopenharmony_ci
104616d0f9Sopenharmony_ci#include "private.h"	/* for time_t and TYPE_SIGNED */
114616d0f9Sopenharmony_ci
124616d0f9Sopenharmony_ci/* Return -X as a double.  Using this avoids casting to 'double'.  */
134616d0f9Sopenharmony_cistatic double
144616d0f9Sopenharmony_cidminus(double x)
154616d0f9Sopenharmony_ci{
164616d0f9Sopenharmony_ci  return -x;
174616d0f9Sopenharmony_ci}
184616d0f9Sopenharmony_ci
194616d0f9Sopenharmony_cidouble
204616d0f9Sopenharmony_cidifftime(time_t time1, time_t time0)
214616d0f9Sopenharmony_ci{
224616d0f9Sopenharmony_ci	/*
234616d0f9Sopenharmony_ci	** If double is large enough, simply convert and subtract
244616d0f9Sopenharmony_ci	** (assuming that the larger type has more precision).
254616d0f9Sopenharmony_ci	*/
264616d0f9Sopenharmony_ci	if (sizeof(time_t) < sizeof(double)) {
274616d0f9Sopenharmony_ci	  double t1 = time1, t0 = time0;
284616d0f9Sopenharmony_ci	  return t1 - t0;
294616d0f9Sopenharmony_ci	}
304616d0f9Sopenharmony_ci
314616d0f9Sopenharmony_ci	/*
324616d0f9Sopenharmony_ci	** The difference of two unsigned values can't overflow
334616d0f9Sopenharmony_ci	** if the minuend is greater than or equal to the subtrahend.
344616d0f9Sopenharmony_ci	*/
354616d0f9Sopenharmony_ci	if (!TYPE_SIGNED(time_t))
364616d0f9Sopenharmony_ci	  return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
374616d0f9Sopenharmony_ci
384616d0f9Sopenharmony_ci	/* Use uintmax_t if wide enough.  */
394616d0f9Sopenharmony_ci	if (sizeof(time_t) <= sizeof(uintmax_t)) {
404616d0f9Sopenharmony_ci	  uintmax_t t1 = time1, t0 = time0;
414616d0f9Sopenharmony_ci	  return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
424616d0f9Sopenharmony_ci	}
434616d0f9Sopenharmony_ci
444616d0f9Sopenharmony_ci	/*
454616d0f9Sopenharmony_ci	** Handle cases where both time1 and time0 have the same sign
464616d0f9Sopenharmony_ci	** (meaning that their difference cannot overflow).
474616d0f9Sopenharmony_ci	*/
484616d0f9Sopenharmony_ci	if ((time1 < 0) == (time0 < 0))
494616d0f9Sopenharmony_ci	  return time1 - time0;
504616d0f9Sopenharmony_ci
514616d0f9Sopenharmony_ci	/*
524616d0f9Sopenharmony_ci	** The values have opposite signs and uintmax_t is too narrow.
534616d0f9Sopenharmony_ci	** This suffers from double rounding; attempt to lessen that
544616d0f9Sopenharmony_ci	** by using long double temporaries.
554616d0f9Sopenharmony_ci	*/
564616d0f9Sopenharmony_ci	{
574616d0f9Sopenharmony_ci	  long double t1 = time1, t0 = time0;
584616d0f9Sopenharmony_ci	  return t1 - t0;
594616d0f9Sopenharmony_ci	}
604616d0f9Sopenharmony_ci}
61