This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][BZ #15799] Make div cross-platform.


Hi, following bug report complains that division does not satisfy c
standard.

Following fix uses unsigned division for defined behavior. My original
view was that this code is not performance critical as gcc expands div
calls. However this is false as following is not optimized.

#include <stdlib.h>
int foo(int x, int y){
  div_t d = div (x, 3);
  return d.quot + d.rem;
}

This should be fast when both numerator and denumerators are positive,
is trying to optimize it more worth it?

	[BZ #15799]
	* stdlib/div.c (div): Compute result in cross-platform way.

diff --git a/stdlib/div.c b/stdlib/div.c
index 44a30a7..db3a7d0 100644
--- a/stdlib/div.c
+++ b/stdlib/div.c
@@ -55,31 +55,40 @@ div (numer, denom)
      int numer, denom;
 {
   div_t result;
-
-  result.quot = numer / denom;
-  result.rem = numer % denom;
+  unsigned int unumer = numer, udenom = denom;
 
   /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where
      NUMER / DENOM is to be computed in infinite precision.  In
      other words, we should always truncate the quotient towards
      zero, never -infinity.  Machine division and remainer may
      work either way when one or both of NUMER or DENOM is
-     negative.  If only one is negative and QUOT has been
-     truncated towards -infinity, REM will have the same sign as
-     DENOM and the opposite sign of NUMER; if both are negative
-     and QUOT has been truncated towards -infinity, REM will be
-     positive (will have the opposite sign of NUMER).  These are
-     considered `wrong'.  If both are NUM and DENOM are positive,
-     RESULT will always be positive.  This all boils down to: if
-     NUMER >= 0, but REM < 0, we got the wrong answer.  In that
-     case, to get the right answer, add 1 to QUOT and subtract
-     DENOM from REM.  */
-
-  if (numer >= 0 && result.rem < 0)
-    {
-      ++result.quot;
-      result.rem -= denom;
-    }
+     negative.  We use unsigned division which has defined behaviour.  */
 
+  if (numer >= 0)
+    if (denom >= 0)
+      {
+	result.quot = unumer / udenom;
+	result.rem = unumer % udenom;
+      }
+    else
+      {
+	udenom = - udenom;
+	result.quot = - (unumer / udenom);
+	result.rem = - (unumer % udenom);
+      }
+  else
+    if (denom >= 0)
+      {
+	unumer = - unumer;
+	result.quot = - (unumer / udenom);
+	result.rem = - (unumer % udenom);
+      }
+    else
+      {
+	unumer = - unumer;
+	udenom = - udenom;
+	result.quot = unumer / udenom;
+	result.rem = unumer % udenom;
+      }
   return result;
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]