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