New long_lshift, without restriction on size of shift count, by Tim Peters.

This makes it possible to write 1L<<1000000, memory permitting.
This commit is contained in:
Guido van Rossum 1997-03-16 00:37:59 +00:00
parent e053c67780
commit f2e499b1d7

View file

@ -1214,10 +1214,11 @@ long_lshift(a, b)
longobject *a; longobject *a;
longobject *b; longobject *b;
{ {
/* This version due to Tim Peters */
longobject *z; longobject *z;
long shiftby; long shiftby;
int newsize, wordshift, loshift, hishift, i, j; int oldsize, newsize, wordshift, remshift, i, j;
digit lomask, himask; twodigits accum;
shiftby = getlongvalue((object *)b); shiftby = getlongvalue((object *)b);
if (shiftby == -1L && err_occurred()) if (shiftby == -1L && err_occurred())
@ -1226,26 +1227,18 @@ long_lshift(a, b)
err_setstr(ValueError, "negative shift count"); err_setstr(ValueError, "negative shift count");
return NULL; return NULL;
} }
if (shiftby > MASK) { if ((long)(int)shiftby != shiftby) {
err_setstr(ValueError, "outrageous left shift count"); err_setstr(ValueError, "outrageous left shift count");
return NULL; return NULL;
} }
if (shiftby % SHIFT == 0) { /* wordshift, remshift = divmod(shiftby, SHIFT) */
wordshift = shiftby / SHIFT; wordshift = (int)shiftby / SHIFT;
loshift = 0; remshift = (int)shiftby - wordshift * SHIFT;
hishift = SHIFT;
newsize = ABS(a->ob_size) + wordshift; oldsize = ABS(a->ob_size);
lomask = MASK; newsize = oldsize + wordshift;
himask = 0; if (remshift)
} ++newsize;
else {
wordshift = shiftby / SHIFT + 1;
loshift = SHIFT - shiftby%SHIFT;
hishift = shiftby % SHIFT;
newsize = ABS(a->ob_size) + wordshift;
lomask = ((digit)1 << hishift) - 1;
himask = MASK ^ lomask;
}
z = alloclongobject(newsize); z = alloclongobject(newsize);
if (z == NULL) if (z == NULL)
return NULL; return NULL;
@ -1253,13 +1246,16 @@ long_lshift(a, b)
z->ob_size = -(z->ob_size); z->ob_size = -(z->ob_size);
for (i = 0; i < wordshift; i++) for (i = 0; i < wordshift; i++)
z->ob_digit[i] = 0; z->ob_digit[i] = 0;
for (i = wordshift, j = 0; i < newsize; i++, j++) { accum = 0;
if (i > 0) for (i = wordshift, j = 0; j < oldsize; i++, j++) {
z->ob_digit[i-1] |= accum |= a->ob_digit[j] << remshift;
(a->ob_digit[j] << hishift) & himask; z->ob_digit[i] = (digit)(accum & MASK);
z->ob_digit[i] = accum >>= SHIFT;
(a->ob_digit[j] >> loshift) & lomask;
} }
if (remshift)
z->ob_digit[newsize-1] = (digit)accum;
else
assert(!accum);
return (object *) long_normalize(z); return (object *) long_normalize(z);
} }