mirror of https://github.com/python/cpython
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:
parent
9279ec2504
commit
bd3a527f93
|
@ -315,9 +315,11 @@ PyLong_FromLongLong(ival)
|
||||||
#else
|
#else
|
||||||
if( ival <= (long long)LONG_MAX ) {
|
if( ival <= (long long)LONG_MAX ) {
|
||||||
return PyLong_FromLong( (long)ival );
|
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 );
|
return PyLong_FromUnsignedLong( (unsigned long)ival );
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/* Assume a C long long fits in at most 10 'digits'.
|
/* Assume a C long long fits in at most 10 'digits'.
|
||||||
* Should be OK if we're assuming long fits in 5.
|
* Should be OK if we're assuming long fits in 5.
|
||||||
*/
|
*/
|
||||||
|
@ -359,7 +361,8 @@ PyLong_FromUnsignedLongLong(ival)
|
||||||
#else
|
#else
|
||||||
if( ival <= (unsigned long long)ULONG_MAX ) {
|
if( ival <= (unsigned long long)ULONG_MAX ) {
|
||||||
return PyLong_FromUnsignedLong( (unsigned long)ival );
|
return PyLong_FromUnsignedLong( (unsigned long)ival );
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
/* Assume a C long fits in at most 10 'digits'. */
|
/* Assume a C long fits in at most 10 'digits'. */
|
||||||
PyLongObject *v = _PyLong_New(10);
|
PyLongObject *v = _PyLong_New(10);
|
||||||
|
|
||||||
|
@ -572,30 +575,71 @@ long_format(aa, base)
|
||||||
if (a->ob_size < 0)
|
if (a->ob_size < 0)
|
||||||
sign = '-';
|
sign = '-';
|
||||||
|
|
||||||
Py_INCREF(a);
|
if (a->ob_size == 0) {
|
||||||
do {
|
*--p = '0';
|
||||||
digit rem;
|
}
|
||||||
PyLongObject *temp = divrem1(a, (digit)base, &rem);
|
else if ((base & (base - 1)) == 0) {
|
||||||
if (temp == NULL) {
|
/* JRH: special case for power-of-2 bases */
|
||||||
Py_DECREF(a);
|
twodigits temp = a->ob_digit[0];
|
||||||
Py_DECREF(str);
|
int bitsleft = SHIFT;
|
||||||
return NULL;
|
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 {
|
||||||
else
|
Py_INCREF(a);
|
||||||
rem += 'A'-10;
|
do {
|
||||||
assert(p > PyString_AS_STRING(str));
|
digit rem;
|
||||||
*--p = (char) rem;
|
PyLongObject *temp = divrem1(a, (digit)base, &rem);
|
||||||
Py_DECREF(a);
|
if (temp == NULL) {
|
||||||
a = temp;
|
Py_DECREF(a);
|
||||||
SIGCHECK({
|
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(a);
|
||||||
Py_DECREF(str);
|
a = temp;
|
||||||
return NULL;
|
SIGCHECK({
|
||||||
})
|
Py_DECREF(a);
|
||||||
} while (ABS(a->ob_size) != 0);
|
Py_DECREF(str);
|
||||||
Py_DECREF(a);
|
return NULL;
|
||||||
|
})
|
||||||
|
} while (ABS(a->ob_size) != 0);
|
||||||
|
Py_DECREF(a);
|
||||||
|
}
|
||||||
|
|
||||||
if (base == 8) {
|
if (base == 8) {
|
||||||
if (size_a != 0)
|
if (size_a != 0)
|
||||||
*--p = '0';
|
*--p = '0';
|
||||||
|
@ -723,7 +767,8 @@ long_divrem(a, b, pdiv, prem)
|
||||||
PyLongObject *z;
|
PyLongObject *z;
|
||||||
|
|
||||||
if (size_b == 0) {
|
if (size_b == 0) {
|
||||||
PyErr_SetString(PyExc_ZeroDivisionError, "long division or modulo");
|
PyErr_SetString(PyExc_ZeroDivisionError,
|
||||||
|
"long division or modulo");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (size_a < size_b ||
|
if (size_a < size_b ||
|
||||||
|
@ -1520,17 +1565,6 @@ long_bitwise(a, op, b)
|
||||||
maskb = 0;
|
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;
|
negz = 0;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case '^':
|
case '^':
|
||||||
|
@ -1557,6 +1591,31 @@ long_bitwise(a, op, b)
|
||||||
break;
|
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) {
|
for (i = 0; i < size_z; ++i) {
|
||||||
diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
|
diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
|
||||||
digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;
|
digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;
|
||||||
|
|
Loading…
Reference in New Issue