1984263bcSMatthew Dillon /* 2984263bcSMatthew Dillon ** This file is in the public domain, so clarified as of 30e2a9149SSascha Wildner ** 1996-06-05 by Arthur David Olson. 4984263bcSMatthew Dillon ** 50d5acd74SJohn Marino ** $FreeBSD: head/contrib/tzcode/stdtime/difftime.c 192625 2009-05-23 06:31:50Z edwin $ 61de703daSMatthew Dillon */ 7984263bcSMatthew Dillon /*LINTLIBRARY*/ 8984263bcSMatthew Dillon 917ea2221SMatthew Dillon #include "namespace.h" 10*59d71b6fSSascha Wildner #include "private.h" /* for time_t and TYPE_SIGNED */ 1117ea2221SMatthew Dillon #include "un-namespace.h" 12984263bcSMatthew Dillon 13984263bcSMatthew Dillon double difftime(time_t time1,time_t time0)14*59d71b6fSSascha Wildnerdifftime(time_t time1, time_t time0) 15984263bcSMatthew Dillon { 160e2a9149SSascha Wildner /* 170e2a9149SSascha Wildner ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract 180e2a9149SSascha Wildner ** (assuming that the larger type has more precision). 190e2a9149SSascha Wildner */ 200e2a9149SSascha Wildner if (sizeof (double) > sizeof (time_t)) 21984263bcSMatthew Dillon return (double) time1 - (double) time0; 220e2a9149SSascha Wildner if (!TYPE_SIGNED(time_t)) { 23984263bcSMatthew Dillon /* 240e2a9149SSascha Wildner ** The difference of two unsigned values can't overflow 250e2a9149SSascha Wildner ** if the minuend is greater than or equal to the subtrahend. 26984263bcSMatthew Dillon */ 270e2a9149SSascha Wildner if (time1 >= time0) 280e2a9149SSascha Wildner return time1 - time0; 29*59d71b6fSSascha Wildner else return -(double) (time0 - time1); 300e2a9149SSascha Wildner } 31984263bcSMatthew Dillon /* 320e2a9149SSascha Wildner ** Handle cases where both time1 and time0 have the same sign 330e2a9149SSascha Wildner ** (meaning that their difference cannot overflow). 34984263bcSMatthew Dillon */ 350e2a9149SSascha Wildner if ((time1 < 0) == (time0 < 0)) 360e2a9149SSascha Wildner return time1 - time0; 370e2a9149SSascha Wildner /* 380e2a9149SSascha Wildner ** time1 and time0 have opposite signs. 39*59d71b6fSSascha Wildner ** Punt if uintmax_t is too narrow. 40*59d71b6fSSascha Wildner ** This suffers from double rounding; attempt to lessen that 41*59d71b6fSSascha Wildner ** by using long double temporaries. 420e2a9149SSascha Wildner */ 43*59d71b6fSSascha Wildner if (sizeof (uintmax_t) < sizeof (time_t)) 44*59d71b6fSSascha Wildner return (long double) time1 - (long double) time0; 450e2a9149SSascha Wildner /* 460e2a9149SSascha Wildner ** Stay calm...decent optimizers will eliminate the complexity below. 470e2a9149SSascha Wildner */ 480e2a9149SSascha Wildner if (time1 >= 0 /* && time0 < 0 */) 49*59d71b6fSSascha Wildner return (uintmax_t) time1 + (uintmax_t) (-1 - time0) + 1; 50*59d71b6fSSascha Wildner return -(double) ((uintmax_t) time0 + (uintmax_t) (-1 - time1) + 1); 51984263bcSMatthew Dillon } 52