[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