difftime.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. /* Return the difference between two timestamps. */
  2. /*
  3. ** This file is in the public domain, so clarified as of
  4. ** 1996-06-05 by Arthur David Olson.
  5. */
  6. /*LINTLIBRARY*/
  7. #include "private.h" /* for time_t and TYPE_SIGNED */
  8. /* Return -X as a double. Using this avoids casting to 'double'. */
  9. static double
  10. dminus(double x)
  11. {
  12. return -x;
  13. }
  14. double
  15. difftime(time_t time1, time_t time0)
  16. {
  17. /*
  18. ** If double is large enough, simply convert and subtract
  19. ** (assuming that the larger type has more precision).
  20. */
  21. if (sizeof(time_t) < sizeof(double)) {
  22. double t1 = time1, t0 = time0;
  23. return t1 - t0;
  24. }
  25. /*
  26. ** The difference of two unsigned values can't overflow
  27. ** if the minuend is greater than or equal to the subtrahend.
  28. */
  29. if (!TYPE_SIGNED(time_t))
  30. return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
  31. /* Use uintmax_t if wide enough. */
  32. if (sizeof(time_t) <= sizeof(uintmax_t)) {
  33. uintmax_t t1 = time1, t0 = time0;
  34. return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
  35. }
  36. /*
  37. ** Handle cases where both time1 and time0 have the same sign
  38. ** (meaning that their difference cannot overflow).
  39. */
  40. if ((time1 < 0) == (time0 < 0))
  41. return time1 - time0;
  42. /*
  43. ** The values have opposite signs and uintmax_t is too narrow.
  44. ** This suffers from double rounding; attempt to lessen that
  45. ** by using long double temporaries.
  46. */
  47. {
  48. long double t1 = time1, t0 = time0;
  49. return t1 - t0;
  50. }
  51. }