[Python-checkins] CVS: python/dist/src/Objects longobject.c,1.72,1.73

Tim Peters tim_one@users.sourceforge.net
Mon, 11 Jun 2001 18:22:24 -0700


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

Modified Files:
	longobject.c 
Log Message:
Added q/Q standard (x-platform 8-byte ints) mode in struct module.
This completes the q/Q project.

longobject.c _PyLong_AsByteArray:  The original code had a gross bug:
the most-significant Python digit doesn't necessarily have SHIFT
significant bits, and you really need to count how many copies of the sign
bit it has else spurious overflow errors result.

test_struct.py:  This now does exhaustive std q/Q testing at, and on both
sides of, all relevant power-of-2 boundaries, both positive and negative.

NEWS:  Added brief dict news while I was at it.


Index: longobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/longobject.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -C2 -r1.72 -r1.73
*** longobject.c	2001/06/11 21:23:58	1.72
--- longobject.c	2001/06/12 01:22:22	1.73
***************
*** 365,368 ****
--- 365,369 ----
  	carry = do_twos_comp ? 1 : 0;
  	for (i = 0; i < ndigits; ++i) {
+ 		unsigned int oldaccumbits = accumbits;
  		twodigits thisdigit = v->ob_digit[i];
  		if (do_twos_comp) {
***************
*** 371,382 ****
  			thisdigit &= MASK;
  		}
  		/* Because we're going LSB to MSB, thisdigit is more
  		   significant than what's already in accum, so needs to be
  		   prepended to accum. */
! 		accum |= thisdigit << accumbits;
! 		accumbits += SHIFT;
  		/* Store as many bytes as possible. */
! 		assert(accumbits >= 8);
! 		do {
  			if (j >= n)
  				goto Overflow;
--- 372,395 ----
  			thisdigit &= MASK;
  		}
+ 		if (i < ndigits - 1)
+ 			accumbits += SHIFT;
+ 		else {
+ 			/* The most-significant digit may be partly empty. */
+ 			twodigits bitmask = 1 << (SHIFT - 1);
+ 			twodigits signbit = do_twos_comp << (SHIFT - 1);
+ 			unsigned int nsignbits = 0;
+ 			while ((thisdigit & bitmask) == signbit && bitmask) {
+ 				++nsignbits;
+ 				bitmask >>= 1;
+ 				signbit >>= 1;
+ 			}
+ 			accumbits += SHIFT - nsignbits;
+ 		}
  		/* Because we're going LSB to MSB, thisdigit is more
  		   significant than what's already in accum, so needs to be
  		   prepended to accum. */
! 		accum |= thisdigit << oldaccumbits;
  		/* Store as many bytes as possible. */
! 		while (accumbits >= 8) {
  			if (j >= n)
  				goto Overflow;
***************
*** 386,390 ****
  			accumbits -= 8;
  			accum >>= 8;
! 		} while (accumbits >= 8);
  	}
  
--- 399,403 ----
  			accumbits -= 8;
  			accum >>= 8;
! 		}
  	}
  
***************
*** 392,396 ****
  	assert(accumbits < 8);
  	assert(carry == 0);  /* else do_twos_comp and *every* digit was 0 */
! 	if (accum) {
  		if (j >= n)
  			goto Overflow;
--- 405,409 ----
  	assert(accumbits < 8);
  	assert(carry == 0);  /* else do_twos_comp and *every* digit was 0 */
! 	if (accumbits > 0) {
  		if (j >= n)
  			goto Overflow;