>From d3c70b9025d5bca633b9ea1d43985ceabc5fa931 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 27 Jul 2015 11:20:44 -0700
Subject: [PATCH 2/7] Avoid unnecessary casts in difftime

* difftime.c (dminus): New static function.
(difftime): Use it, and rewrite to avoid need for casts.
While we're at it, simplify the code by assuming that
time_t is an integer type; this follows up on the August 2013
change that removed support for floating-point time_t.
---
 difftime.c | 54 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/difftime.c b/difftime.c
index 5ee8eec..ba2fd03 100644
--- a/difftime.c
+++ b/difftime.c
@@ -7,42 +7,52 @@
 
 #include "private.h"	/* for time_t and TYPE_SIGNED */
 
+/* Return -X as a double.  Using this avoids casting to 'double'.  */
+static double
+dminus(double x)
+{
+  return -x;
+}
+
 double ATTRIBUTE_CONST
 difftime(time_t time1, time_t time0)
 {
 	/*
-	** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
+	** If double is large enough, simply convert and subtract
 	** (assuming that the larger type has more precision).
 	*/
-	if (sizeof (double) > sizeof (time_t))
-		return (double) time1 - (double) time0;
-	if (!TYPE_SIGNED(time_t)) {
-		/*
-		** The difference of two unsigned values can't overflow
-		** if the minuend is greater than or equal to the subtrahend.
-		*/
-		if (time1 >= time0)
-			return            time1 - time0;
-		else	return -(double) (time0 - time1);
+	if (sizeof (time_t) < sizeof (double)) {
+	  double t1 = time1, t0 = time0;
+	  return t1 - t0;
 	}
+
+	/*
+	** The difference of two unsigned values can't overflow
+	** if the minuend is greater than or equal to the subtrahend.
+	*/
+	if (!TYPE_SIGNED(time_t))
+	  return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
+
+	/* Use uintmax_t if wide enough.  */
+	if (sizeof (time_t) <= sizeof (uintmax_t)) {
+	  uintmax_t t1 = time1, t0 = time0;
+	  return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
+	}
+
 	/*
 	** Handle cases where both time1 and time0 have the same sign
 	** (meaning that their difference cannot overflow).
 	*/
 	if ((time1 < 0) == (time0 < 0))
-		return time1 - time0;
+	  return time1 - time0;
+
 	/*
-	** time1 and time0 have opposite signs.
-	** Punt if uintmax_t is too narrow.
+	** The values have opposite signs and uintmax_t is too narrow.
 	** This suffers from double rounding; attempt to lessen that
 	** by using long double temporaries.
 	*/
-	if (sizeof (uintmax_t) < sizeof (time_t))
-		return (long double) time1 - (long double) time0;
-	/*
-	** Stay calm...decent optimizers will eliminate the complexity below.
-	*/
-	if (time1 >= 0 /* && time0 < 0 */)
-		return    (uintmax_t) time1 + (uintmax_t) (-1 - time0) + 1;
-	return -(double) ((uintmax_t) time0 + (uintmax_t) (-1 - time1) + 1);
+	{
+	  long double t1 = time1, t0 = time0;
+	  return t1 - t0;
+	}
 }
-- 
2.1.4

