1/*
2** This file is in the public domain, so clarified as of
3** 1996-06-05 by Arthur David Olson.
4*/
5
6#ifndef lint
7#ifndef NOID
8static char elsieid[] = "@(#)difftime.c 8.1";
9#endif /* !defined NOID */
10#endif /* !defined lint */
11
12/*LINTLIBRARY*/
13
14#include "private.h"    /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
15
16double
17difftime(time1, time0)
18const time_t    time1;
19const time_t    time0;
20{
21    /*
22    ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
23    ** (assuming that the larger type has more precision).
24    ** This is the common real-world case circa 2004.
25    */
26    if (sizeof (double) > sizeof (time_t))
27        return (double) time1 - (double) time0;
28    if (!TYPE_INTEGRAL(time_t)) {
29        /*
30        ** time_t is floating.
31        */
32        return time1 - time0;
33    }
34    if (!TYPE_SIGNED(time_t)) {
35        /*
36        ** time_t is integral and unsigned.
37        ** The difference of two unsigned values can't overflow
38        ** if the minuend is greater than or equal to the subtrahend.
39        */
40        if (time1 >= time0)
41            return time1 - time0;
42        else    return -((double) (time0 - time1));
43    }
44    /*
45    ** time_t is integral and signed.
46    ** Handle cases where both time1 and time0 have the same sign
47    ** (meaning that their difference cannot overflow).
48    */
49    if ((time1 < 0) == (time0 < 0))
50        return time1 - time0;
51    /*
52    ** time1 and time0 have opposite signs.
53    ** Punt if unsigned long is too narrow.
54    */
55    if (sizeof (unsigned long) < sizeof (time_t))
56        return (double) time1 - (double) time0;
57    /*
58    ** Stay calm...decent optimizers will eliminate the complexity below.
59    */
60    if (time1 >= 0 /* && time0 < 0 */)
61        return (unsigned long) time1 +
62            (unsigned long) (-(time0 + 1)) + 1;
63    return -(double) ((unsigned long) time0 +
64        (unsigned long) (-(time1 + 1)) + 1);
65}
66