[Python-checkins] CVS: python/dist/src/Objects intobject.c,2.56,2.57

Tim Peters tim_one@users.sourceforge.net
Mon, 18 Jun 2001 12:21:13 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv27024/python/dist/src/Objects

Modified Files:
	intobject.c 
Log Message:
SF bug 434186: 0x80000000/2 != 0x80000000>>1
i_divmod:  New and simpler algorithm.  Old one returned gibberish on most
boxes when the numerator was -sys.maxint-1.  Oddly enough, it worked in the
release (not debug) build on Windows, because the compiler optimized away
some tricky sign manipulations that were incorrect in this case.
Makes you wonder <wink> ...
Bugfix candidate. 


Index: intobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/intobject.c,v
retrieving revision 2.56
retrieving revision 2.57
diff -C2 -r2.56 -r2.57
*** intobject.c	2001/03/06 12:12:02	2.56
--- intobject.c	2001/06/18 19:21:11	2.57
***************
*** 435,470 ****
  
  static int
! i_divmod(register long xi, register long yi,
           long *p_xdivy, long *p_xmody)
  {
  	long xdivy, xmody;
  	
! 	if (yi == 0) {
  		PyErr_SetString(PyExc_ZeroDivisionError,
  				"integer division or modulo by zero");
  		return -1;
  	}
! 	if (yi < 0) {
! 		if (xi < 0) {
! 			if (yi == -1 && -xi < 0) {
! 				/* most negative / -1 */
! 				err_ovf("integer division");
! 				return -1;
! 			}
! 			xdivy = -xi / -yi;
! 		}
! 		else
! 			xdivy = - (xi / -yi);
! 	}
! 	else {
! 		if (xi < 0)
! 			xdivy = - (-xi / yi);
! 		else
! 			xdivy = xi / yi;
  	}
! 	xmody = xi - xdivy*yi;
! 	if ((xmody < 0 && yi > 0) || (xmody > 0 && yi < 0)) {
! 		xmody += yi;
! 		xdivy -= 1;
  	}
  	*p_xdivy = xdivy;
--- 435,464 ----
  
  static int
! i_divmod(register long x, register long y,
           long *p_xdivy, long *p_xmody)
  {
  	long xdivy, xmody;
  	
! 	if (y == 0) {
  		PyErr_SetString(PyExc_ZeroDivisionError,
  				"integer division or modulo by zero");
  		return -1;
  	}
! 	/* (-sys.maxint-1)/-1 is the only overflow case. */
! 	if (y == -1 && x < 0 && x == -x) {
! 		err_ovf("integer division");
! 		return -1;
  	}
! 	xdivy = x / y;
! 	xmody = x - xdivy * y;
! 	/* If the signs of x and y differ, and the remainder is non-0,
! 	 * C89 doesn't define whether xdivy is now the floor or the
! 	 * ceiling of the infinitely precise quotient.  We want the floor,
! 	 * and we have it iff the remainder's sign matches y's.
! 	 */
! 	if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
! 		xmody += y;
! 		--xdivy;
! 		assert(xmody && ((y ^ xmody) >= 0));
  	}
  	*p_xdivy = xdivy;