[Python-checkins] r51562 - in python/branches/int_unification: Objects/longobject.c Objects/stringobject.c Python/ceval.c
martin.v.loewis
python-checkins at python.org
Thu Aug 24 19:42:12 CEST 2006
Author: martin.v.loewis
Date: Thu Aug 24 19:42:10 2006
New Revision: 51562
Modified:
python/branches/int_unification/Objects/longobject.c
python/branches/int_unification/Objects/stringobject.c
python/branches/int_unification/Python/ceval.c
Log:
Special-case more single-digit operations.
Avoid modifying singleton values.
Fix index computation.
Modified: python/branches/int_unification/Objects/longobject.c
==============================================================================
--- python/branches/int_unification/Objects/longobject.c (original)
+++ python/branches/int_unification/Objects/longobject.c Thu Aug 24 19:42:10 2006
@@ -48,6 +48,14 @@
#define CHECK_SMALL_INT(ival)
#endif
+#define MEDIUM_VALUE(x) ((x)->ob_size < 0 ? -(x)->ob_digit[0] : (x)->ob_digit[0])
+/* If a freshly-allocated long is already shared, it must
+ be a small integer, so negating it must go to PyLong_FromLong */
+#define NEGATE(x) \
+ do if ((x)->ob_refcnt == 1) (x)->ob_size = -(x)->ob_size; \
+ else { PyObject* tmp=PyInt_FromLong(-MEDIUM_VALUE(x)); \
+ Py_DECREF(x); (x) = (PyLongObject*)tmp; } \
+ while(0)
/* For long multiplication, use the O(N**2) school algorithm unless
* both operands contain more than KARATSUBA_CUTOFF digits (this
* being an internal Python long digit, in base BASE).
@@ -105,11 +113,18 @@
PyLongObject *
_PyLong_New(Py_ssize_t size)
{
+ PyLongObject *result;
if (size > PY_SSIZE_T_MAX) {
PyErr_NoMemory();
return NULL;
}
- return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
+ result = PyObject_MALLOC(sizeof(PyLongObject) +
+ (size-1)*sizeof(digit));
+ if (!result) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ return (PyLongObject*)PyObject_INIT_VAR(result, &PyLong_Type, size);
}
PyObject *
@@ -155,7 +170,7 @@
if (ival < BASE) {
/* Fast path for single-digits ints */
- v = PyObject_NEW_VAR(PyLongObject, &PyLong_Type, 1);
+ v = _PyLong_New(1);
if (v) {
v->ob_size = negative ? -1 : 1;
v->ob_digit[0] = ival;
@@ -291,6 +306,11 @@
v = (PyLongObject *)vv;
i = v->ob_size;
+ switch (i) {
+ case -1: return -v->ob_digit[0];
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
sign = 1;
x = 0;
if (i < 0) {
@@ -353,6 +373,11 @@
}
v = (PyLongObject *)vv;
i = v->ob_size;
+ switch (i) {
+ case -1: return -v->ob_digit[0];
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
sign = 1;
x = 0;
if (i < 0) {
@@ -402,6 +427,10 @@
"can't convert negative value to unsigned long");
return (unsigned long) -1;
}
+ switch (i) {
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
while (--i >= 0) {
prev = x;
x = (x << SHIFT) + v->ob_digit[i];
@@ -436,6 +465,10 @@
"can't convert negative value to size_t");
return (size_t) -1;
}
+ switch (i) {
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
while (--i >= 0) {
prev = x;
x = (x << SHIFT) + v->ob_digit[i];
@@ -465,6 +498,10 @@
}
v = (PyLongObject *)vv;
i = v->ob_size;
+ switch (i) {
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
sign = 1;
x = 0;
if (i < 0) {
@@ -1014,6 +1051,7 @@
PY_LONG_LONG
PyLong_AsLongLong(PyObject *vv)
{
+ PyLongObject *v;
PY_LONG_LONG bytes;
int one = 1;
int res;
@@ -1043,6 +1081,12 @@
return -1;
}
+ v = (PyLongObject*)vv;
+ switch(v->ob_size) {
+ case -1: return -v->ob_digit[0];
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
res = _PyLong_AsByteArray(
(PyLongObject *)vv, (unsigned char *)&bytes,
SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
@@ -1060,6 +1104,7 @@
unsigned PY_LONG_LONG
PyLong_AsUnsignedLongLong(PyObject *vv)
{
+ PyLongObject *v;
unsigned PY_LONG_LONG bytes;
int one = 1;
int res;
@@ -1069,6 +1114,12 @@
return (unsigned PY_LONG_LONG)-1;
}
+ v = (PyLongObject*)vv;
+ switch(v->ob_size) {
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
+
res = _PyLong_AsByteArray(
(PyLongObject *)vv, (unsigned char *)&bytes,
SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
@@ -1096,6 +1147,10 @@
return (unsigned long) -1;
}
v = (PyLongObject *)vv;
+ switch(v->ob_size) {
+ case 0: return 0;
+ case 1: return v->ob_digit[0];
+ }
i = v->ob_size;
sign = 1;
x = 0;
@@ -1816,7 +1871,7 @@
(size_a == size_b &&
a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) {
/* |a| < |b|. */
- *pdiv = _PyLong_New(0);
+ *pdiv = (PyLongObject*)PyLong_FromLong(0);
Py_INCREF(a);
*prem = (PyLongObject *) a;
return 0;
@@ -1838,9 +1893,9 @@
the remainder r has the sign of a,
so a = b*z + r. */
if ((a->ob_size < 0) != (b->ob_size < 0))
- z->ob_size = -(z->ob_size);
+ NEGATE(z);
if (a->ob_size < 0 && (*prem)->ob_size != 0)
- (*prem)->ob_size = -((*prem)->ob_size);
+ NEGATE(*prem);
*pdiv = z;
return 0;
}
@@ -1996,6 +2051,11 @@
same value hash to the same value, otherwise comparisons
of mapping keys will turn out weird */
i = v->ob_size;
+ switch(i) {
+ case -1: return v->ob_digit[0]==1 ? -2 : -v->ob_digit[0];
+ case 0: return 0;
+ case 1: return v->ob_digit[1];
+ }
sign = 1;
x = 0;
if (i < 0) {
@@ -2101,7 +2161,7 @@
}
assert(borrow == 0);
if (sign < 0)
- z->ob_size = -(z->ob_size);
+ NEGATE(z);
return long_normalize(z);
}
@@ -2112,6 +2172,9 @@
CONVERT_BINOP((PyObject *)v, (PyObject *)w, &a, &b);
+ if (ABS(a->ob_size) <= 1 && ABS(b->ob_size) <= 1)
+ return PyInt_FromLong(MEDIUM_VALUE(a) +
+ MEDIUM_VALUE(b));
if (a->ob_size < 0) {
if (b->ob_size < 0) {
z = x_add(a, b);
@@ -2139,6 +2202,8 @@
CONVERT_BINOP((PyObject *)v, (PyObject *)w, &a, &b);
+ if (ABS(a->ob_size) <= 1 && ABS(b->ob_size) <= 1)
+ return PyLong_FromLong(MEDIUM_VALUE(a)-MEDIUM_VALUE(b));
if (a->ob_size < 0) {
if (b->ob_size < 0)
z = x_sub(a, b);
@@ -2568,10 +2633,13 @@
return Py_NotImplemented;
}
+ if (ABS(v->ob_size) <= 1 && ABS(w->ob_size) <= 1)
+ return PyLong_FromLong(MEDIUM_VALUE(v)*MEDIUM_VALUE(w));
+
z = k_mul(a, b);
/* Negate if exactly one of the inputs is negative. */
if (((a->ob_size ^ b->ob_size) < 0) && z)
- z->ob_size = -(z->ob_size);
+ NEGATE(z);
Py_DECREF(a);
Py_DECREF(b);
return (PyObject *)z;
@@ -2810,7 +2878,7 @@
Py_DECREF(c);
c = temp;
temp = NULL;
- c->ob_size = - c->ob_size;
+ NEGATE(c);
}
/* if modulus == 1:
@@ -2931,6 +2999,8 @@
/* Implement ~x as -(x+1) */
PyLongObject *x;
PyLongObject *w;
+ if (ABS(v->ob_size) <=1)
+ return PyLong_FromLong(-(MEDIUM_VALUE(v)+1));
w = (PyLongObject *)PyLong_FromLong(1L);
if (w == NULL)
return NULL;
@@ -2957,11 +3027,8 @@
long_neg(PyLongObject *v)
{
PyLongObject *z;
- if (v->ob_size == 0 && PyLong_CheckExact(v)) {
- /* -0 == 0 */
- Py_INCREF(v);
- return (PyObject *) v;
- }
+ if (ABS(v->ob_size) <= 1)
+ return PyLong_FromLong(-MEDIUM_VALUE(v));
z = (PyLongObject *)_PyLong_Copy(v);
if (z != NULL)
z->ob_size = -(v->ob_size);
@@ -3085,7 +3152,7 @@
if (z == NULL)
goto lshift_error;
if (a->ob_size < 0)
- z->ob_size = -(z->ob_size);
+ NEGATE(z);
for (i = 0; i < wordshift; i++)
z->ob_digit[i] = 0;
accum = 0;
Modified: python/branches/int_unification/Objects/stringobject.c
==============================================================================
--- python/branches/int_unification/Objects/stringobject.c (original)
+++ python/branches/int_unification/Objects/stringobject.c Thu Aug 24 19:42:10 2006
@@ -4206,6 +4206,14 @@
int numdigits; /* len == numnondigits + numdigits */
int numnondigits = 0;
+ /* Avoid exceeding SSIZE_T_MAX */
+ if (prec > PY_SSIZE_T_MAX-3) {
+ PyErr_SetString(PyExc_OverflowError,
+ "precision too large");
+ return NULL;
+ }
+
+
switch (type) {
case 'd':
case 'u':
Modified: python/branches/int_unification/Python/ceval.c
==============================================================================
--- python/branches/int_unification/Python/ceval.c (original)
+++ python/branches/int_unification/Python/ceval.c Thu Aug 24 19:42:10 2006
@@ -3819,7 +3819,7 @@
{
if (v != NULL) {
Py_ssize_t x;
- if (PyInt_Check(v)) {
+ if (PyInt_CheckExact(v)) {
/* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
however, it looks like it should be AsSsize_t.
There should be a comment here explaining why.
More information about the Python-checkins
mailing list