# HG changeset patch # Parent 45e1c0029aff105ebc8e3942ae923e4c902ea9f3 diff -r 45e1c0029aff Objects/longobject.c --- a/Objects/longobject.c Fri Sep 26 15:35:02 2014 +0300 +++ b/Objects/longobject.c Fri Sep 26 18:33:01 2014 +0200 @@ -70,6 +70,11 @@ #define maybe_small_long(val) (val) #endif +/* Create a new long based on the Py_SIZE() sign of another + (e.g. fast "* -1" or "* 1"). */ +#define COPY_SIGNED(v, sign) \ + (((sign) < 0) ? long_neg((PyLongObject*)v) : long_long((PyObject*)v)) + /* If a freshly-allocated int is already shared, it must be a small integer, so negating it must go to PyLong_FromLong */ Py_LOCAL_INLINE(void) @@ -2372,6 +2377,7 @@ static PyLongObject *x_divrem (PyLongObject *, PyLongObject *, PyLongObject **); static PyObject *long_long(PyObject *v); +static PyObject *long_neg(PyLongObject *v); /* Int division with remainder, top-level routine */ @@ -3402,23 +3408,39 @@ long_mul(PyLongObject *a, PyLongObject *b) { PyLongObject *z; + Py_ssize_t a_size, b_size; CHECK_BINOP(a, b); + a_size = Py_ABS(Py_SIZE(a)); + b_size = Py_ABS(Py_SIZE(b)); + + if (a_size == 0 || b_size == 0) { + return PyLong_FromLong(0); + } + /* fast path for single-digit multiplication */ - if (Py_ABS(Py_SIZE(a)) <= 1 && Py_ABS(Py_SIZE(b)) <= 1) { - stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b); + if (a_size == 1) { + if (a->ob_digit[0] == 1) + return COPY_SIGNED(b, Py_SIZE(a)); + if (b_size == 1) { + stwodigits v = (stwodigits)(MEDIUM_VALUE(a)) * MEDIUM_VALUE(b); #ifdef HAVE_LONG_LONG - return PyLong_FromLongLong((PY_LONG_LONG)v); + return PyLong_FromLongLong((PY_LONG_LONG)v); #else - /* if we don't have long long then we're almost certainly - using 15-bit digits, so v will fit in a long. In the - unlikely event that we're using 30-bit digits on a platform - without long long, a large v will just cause us to fall - through to the general multiplication code below. */ - if (v >= LONG_MIN && v <= LONG_MAX) - return PyLong_FromLong((long)v); + /* if we don't have long long then we're almost certainly + using 15-bit digits, so v will fit in a long. In the + unlikely event that we're using 30-bit digits on a platform + without long long, a large v will just cause us to fall + through to the general multiplication code below. */ + if (v >= LONG_MIN && v <= LONG_MAX) + return PyLong_FromLong((long)v); #endif + } + } + else if (b_size == 1) { + if (b->ob_digit[0] == 1) + return COPY_SIGNED(a, Py_SIZE(b)); } z = k_mul(a, b); @@ -3458,6 +3480,28 @@ { PyLongObject *div, *mod; + /* Fast path for division by 1 or -1 */ + if (Py_ABS(Py_SIZE(w)) == 1 && w->ob_digit[0] == 1) { + if (pdiv != NULL) { + div = (PyLongObject*)COPY_SIGNED(v, Py_SIZE(w)); + if (div == NULL) + return -1; + } else { + div = NULL; + } + if (pmod != NULL) { + mod = (PyLongObject*)PyLong_FromLong(0); + if (mod == NULL) { + Py_XDECREF(div); + return -1; + } + *pmod = mod; + } + if (pdiv != NULL) + *pdiv = div; + return 0; + } + if (long_divrem(v, w, &div, &mod) < 0) return -1; if ((Py_SIZE(mod) < 0 && Py_SIZE(w) > 0) ||