Two patches by Jason Harper:

- Faster conversion to string for binary bases: linear instead of quadratic!

- Allocate smaller result for certain masking ops, e.g. (1L<<30000) & 1.
This commit is contained in:
Guido van Rossum 1998-08-11 15:04:47 +00:00
parent 9279ec2504
commit bd3a527f93
1 changed files with 96 additions and 37 deletions

View File

@ -315,9 +315,11 @@ PyLong_FromLongLong(ival)
#else
if( ival <= (long long)LONG_MAX ) {
return PyLong_FromLong( (long)ival );
} else if( ival <= (unsigned long long)ULONG_MAX ) {
}
else if( ival <= (unsigned long long)ULONG_MAX ) {
return PyLong_FromUnsignedLong( (unsigned long)ival );
} else {
}
else {
/* Assume a C long long fits in at most 10 'digits'.
* Should be OK if we're assuming long fits in 5.
*/
@ -359,7 +361,8 @@ PyLong_FromUnsignedLongLong(ival)
#else
if( ival <= (unsigned long long)ULONG_MAX ) {
return PyLong_FromUnsignedLong( (unsigned long)ival );
} else {
}
else {
/* Assume a C long fits in at most 10 'digits'. */
PyLongObject *v = _PyLong_New(10);
@ -572,30 +575,71 @@ long_format(aa, base)
if (a->ob_size < 0)
sign = '-';
Py_INCREF(a);
do {
digit rem;
PyLongObject *temp = divrem1(a, (digit)base, &rem);
if (temp == NULL) {
Py_DECREF(a);
Py_DECREF(str);
return NULL;
if (a->ob_size == 0) {
*--p = '0';
}
else if ((base & (base - 1)) == 0) {
/* JRH: special case for power-of-2 bases */
twodigits temp = a->ob_digit[0];
int bitsleft = SHIFT;
int rem;
int last = abs(a->ob_size);
int basebits = 1;
i = base;
while ((i >>= 1) > 1) ++basebits;
i = 0;
for (;;) {
while (bitsleft >= basebits) {
if ((temp == 0) && (i >= last - 1)) break;
rem = temp & (base - 1);
if (rem < 10)
rem += '0';
else
rem += 'A' - 10;
assert(p > PyString_AS_STRING(str));
*--p = (char) rem;
bitsleft -= basebits;
temp >>= basebits;
}
if (++i >= last) {
if (temp == 0) break;
bitsleft = 99;
/* loop again to pick up final digits */
}
else {
temp = (a->ob_digit[i] << bitsleft) | temp;
bitsleft += SHIFT;
}
}
if (rem < 10)
rem += '0';
else
rem += 'A'-10;
assert(p > PyString_AS_STRING(str));
*--p = (char) rem;
Py_DECREF(a);
a = temp;
SIGCHECK({
}
else {
Py_INCREF(a);
do {
digit rem;
PyLongObject *temp = divrem1(a, (digit)base, &rem);
if (temp == NULL) {
Py_DECREF(a);
Py_DECREF(str);
return NULL;
}
if (rem < 10)
rem += '0';
else
rem += 'A'-10;
assert(p > PyString_AS_STRING(str));
*--p = (char) rem;
Py_DECREF(a);
Py_DECREF(str);
return NULL;
})
} while (ABS(a->ob_size) != 0);
Py_DECREF(a);
a = temp;
SIGCHECK({
Py_DECREF(a);
Py_DECREF(str);
return NULL;
})
} while (ABS(a->ob_size) != 0);
Py_DECREF(a);
}
if (base == 8) {
if (size_a != 0)
*--p = '0';
@ -723,7 +767,8 @@ long_divrem(a, b, pdiv, prem)
PyLongObject *z;
if (size_b == 0) {
PyErr_SetString(PyExc_ZeroDivisionError, "long division or modulo");
PyErr_SetString(PyExc_ZeroDivisionError,
"long division or modulo");
return -1;
}
if (size_a < size_b ||
@ -1520,17 +1565,6 @@ long_bitwise(a, op, b)
maskb = 0;
}
size_a = a->ob_size;
size_b = b->ob_size;
size_z = MAX(size_a, size_b);
z = _PyLong_New(size_z);
if (a == NULL || b == NULL || z == NULL) {
Py_XDECREF(a);
Py_XDECREF(b);
Py_XDECREF(z);
return NULL;
}
negz = 0;
switch (op) {
case '^':
@ -1557,6 +1591,31 @@ long_bitwise(a, op, b)
break;
}
/* JRH: The original logic here was to allocate the result value (z)
as the longer of the two operands. However, there are some cases
where the result is guaranteed to be shorter than that: AND of two
positives, OR of two negatives: use the shorter number. AND with
mixed signs: use the positive number. OR with mixed signs: use the
negative number. After the transformations above, op will be '&'
iff one of these cases applies, and mask will be non-0 for operands
whose length should be ignored.
*/
size_a = a->ob_size;
size_b = b->ob_size;
size_z = op == '&'
? (maska
? size_b
: (maskb ? size_a : MIN(size_a, size_b)))
: MAX(size_a, size_b);
z = _PyLong_New(size_z);
if (a == NULL || b == NULL || z == NULL) {
Py_XDECREF(a);
Py_XDECREF(b);
Py_XDECREF(z);
return NULL;
}
for (i = 0; i < size_z; ++i) {
diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;